Files
pcre2/maint/ManyConfigTests
Nicholas Wilson 500c68b986 Add testing for malloc() failures (#697)
An additional testing argument, `-malloc` is added to pcre2test and to RunTest.

The ManyConfig tests run this now in CI.

We exercise each malloc failure in the core code by counting how many mallocs are done, then repeating compilation and matching with a failure on each successive malloc.
2025-02-23 09:51:32 +00:00

544 lines
16 KiB
Bash
Executable File

#! /bin/sh
# This is a script for the use of PCRE2 maintainers. It configures and builds
# PCRE2 with a variety of configuration options, and in each case runs the
# tests to ensure that all goes well. Every possible combination would take far
# too long, so we use a representative sample. This script should be run in the
# PCRE2 source directory.
# While debugging, it is sometimes useful to be able to cut out some of the
# tests, in order to run those that are giving errors. The following options
# do this:
#
# -noasan skip the test that uses -fsanitize=address
# -nousan skip the test that uses -fsanitize=undefined
# -nodebug skip the test that uses --enable-debug
# -nojit skip all JIT tests
# -nojitmain skip non-valgrind JIT tests
# -nojitvalgrind skip JIT tests with valgrind
# -nomain skip all the main (non-JIT) set of tests
# -nomainvalgrind skip the main (non-JIT) valgrind tests
# -notmp skip the tests in a temporary directory
# -notmpjit skip the JIT test in a temporary directory
# -noebcdic skip the EBCDIC tests
# -novalgrind skip all the valgrind tests
# Alternatively, if any of those names are given with '+' instead of '-no',
# only those groups named with '+' are run (e.g. +jit). If -dummy is given,
# no tests are actually run - this provides a means of testing the selectors.
# The -v option causes a call to 'pcre2test -C' to happen for each
# configuration.
useasan=1
useusan=1
usedebug=1
usejit=1
usejitvalgrind=1
usemain=1
usemainvalgrind=1
usetmp=1
usetmpjit=1
useebcdic=1
usebcdicjit=1
usevalgrind=1
dummy=0
seenplus=0
verbose=0
while [ $# -gt 0 ] ; do
case $1 in
+*) if [ $seenplus -eq 0 ]; then
useasan=0
useusan=0
usedebug=0
usejit=0
usejitvalgrind=0
usemain=0
usemainvalgrind=0
usetmp=0
usetmpjit=0
useebcdic=0
useebcdicjit=0
usevalgrind=0
seenplus=1
fi;;
esac
case $1 in
-dummy) dummy=1;;
-v) verbose=1;;
-noasan) useasan=0;;
-nousan) useusan=0;;
-nodebug) usedebug=0;;
-nojit) usejit=0; usejitvalgrind=0; usetmpjit=0; useebcdicjit=0;;
-nojitmain) usejit=0;;
-nojitvalgrind) usejitvalgrind=0;;
-nomain) usemain=0; usemainvalgrind=0;;
-nomainvalgrind) usemainvalgrind=0;;
-notmp) usetmp=0; usetmpjit=0;;
-notmpjit) usetmpjit=0;;
-noebcdic) useebcdic=0; useebcdicjit=0;;
-noebcdicjit) useebcdicjit=0;;
-novalgrind) usevalgrind=0;;
+asan) useasan=1;;
+usan) useusan=1;;
+debug) usedebug=1;;
+jit) usejit=1; usejitvalgrind=1; usetmpjit=1; useebcdicjit=1;;
+jitmain) usejit=1;;
+jitvalgrind) usejitvalgrind=1;;
+main) usemain=1; usemainvalgrind=1;;
+mainvalgrind) usemainvalgrind=1;;
+tmp) usetmp=1;;
+tmpjit) usetmpjit=1;;
+ebcdic) useebcdic=1;;
+ebcdicjit) useebcdicjit=1;;
+valgrind) usevalgrind=1; usejitvalgrind=1; usemainvalgrind=1;;
*) echo "Unknown option '$1'"; exit 1;;
esac
shift
done
if [ $usejitvalgrind -eq 0 -a $usemainvalgrind -eq 0 ] ; then
usevalgrind=0
fi
# This is in case the caller has set aliases (as I do - PH)
unset cp ls mv rm
# This is a temporary directory for testing out-of-line builds
tmp=/tmp/pcre2testing
# Don't bother with compiler optimization for most tests; it just slows down
# compilation a lot (and running the tests themselves is quick). However, one
# special test turns optimization on, because it can provoke some compiler
# warnings.
CFLAGS="-g"
OFLAGS="-O0"
CC="${CC:=cc}"
ISGCC=0
# If the compiler is GCC, add a lot of warning switches.
CC_VER_OUTPUT=`printf '#if defined(__GNUC__) && !defined(__clang__)\nGCC=yes\n#endif\n' | $CC -E -`
if [ $? -eq 0 ] && (echo "$CC_VER_OUTPUT" | grep GCC=yes) >/dev/null; then
echo "Treating $CC as GCC"
ISGCC=1
CFLAGS="$CFLAGS -Wall"
CFLAGS="$CFLAGS -Wextra"
CFLAGS="$CFLAGS -Wno-overlength-strings"
CFLAGS="$CFLAGS -Wpointer-arith"
CFLAGS="$CFLAGS -Wwrite-strings"
CFLAGS="$CFLAGS -Wundef"
CFLAGS="$CFLAGS -Wshadow"
CFLAGS="$CFLAGS -Wmissing-field-initializers"
CFLAGS="$CFLAGS -Wunused-parameter"
CFLAGS="$CFLAGS -Wformat"
CFLAGS="$CFLAGS -Wbad-function-cast"
CFLAGS="$CFLAGS -Wmissing-declarations"
CFLAGS="$CFLAGS -Wnested-externs"
CFLAGS="$CFLAGS -pedantic"
CFLAGS="$CFLAGS -Wuninitialized"
CFLAGS="$CFLAGS -Wmaybe-uninitialized"
CFLAGS="$CFLAGS -Wmissing-prototypes"
CFLAGS="$CFLAGS -Wstrict-prototypes"
CFLAGS="$CFLAGS -Warray-bounds"
CFLAGS="$CFLAGS -Wformat-overflow=2"
CFLAGS="$CFLAGS -Wformat-truncation=1"
CFLAGS="$CFLAGS -Wdeclaration-after-statement"
fi
# This function runs a single test with the set of configuration options that
# are in $opts. The source directory must be set in srcdir. The function must
# be defined as "runtest()" not "function runtest()" in order to run on
# Solaris.
runtest()
{
rm -f $srcdir/pcre2test $srcdir/pcre2grep $srcdir/pcre2_jit_test $srcdir/pcre2posix_test
testcount=`expr $testcount + 1`
if [ "$opts" = "" ] ; then
echo "[$testcount/$testtotal] Configuring with: default settings"
else
echo "[$testcount/$testtotal] Configuring with:"
echo " $opts"
fi
if [ $dummy -eq 1 ]; then return; fi
CC="$CC" CFLAGS="$CFLAGS" \
$srcdir/configure $opts >/dev/null 2>teststderrM
if [ $? -ne 0 ]; then
echo " "
echo "******** Error while configuring ********"
cat teststderrM
exit 1
fi
# There is an infelicity in the Autotools world (as of October 2015) which
# causes the message
#
# ar: `u' modifier ignored since `D' is the default (see `U')
#
# to be output while linking. This triggers an unwanted error report from this
# script, because it expects no stderr output while making. To get round this
# we filter the stderr output through sed, removing all occurrences of the
# above lines. Just for paranoia, check that sed is available before doing
# this.
echo "Making"
make -j >/dev/null 2>teststderrM
makeRC=$?
if command -v sed >/dev/null 2>&1 ; then
sed "/\`u' modifier ignored since \`D' is the default/ d" \
teststderrM > teststderrMM
mv -f teststderrMM teststderrM
fi
if [ $makeRC -ne 0 -o -s teststderrM ]; then
echo " "
echo "******** Errors or warnings while making ********"
echo " "
cat teststderrM
exit 1
fi
if [ $verbose -eq 1 ]; then
./pcre2test -C
fi
./pcre2test -C jit >/dev/null
jit=$?
./pcre2test -C pcre2-8 >/dev/null
pcre2_8=$?
echo "Running PCRE2 library tests $withvalgrind $withmalloc"
$srcdir/RunTest $valgrind $malloc >teststdoutM 2>teststderrM
if [ $? -ne 0 -o -s teststderrM ]; then
echo " "
echo "**** Test failed ****"
if [ -s teststderrM ] ; then
cat teststderrM
else
cat teststdoutM
fi
exit 1
fi
if [ $pcre2_8 -eq 0 ]; then
echo "Skipping pcre2grep and pcre2posix tests: 8-bit library not compiled"
elif [ "x$withebcdic" != x ]; then
echo "Skipping pcre2grep and pcre2posix tests: tests not supported on EBCDIC"
else
echo "Running pcre2grep tests $withvalgrind"
$srcdir/RunGrepTest $valgrind >teststdoutM 2>teststderrM
if [ $? -ne 0 -o -s teststderrM ]; then
echo " "
echo "**** Test failed ****"
cat teststderrM
cat teststdoutM
exit 1
fi
echo "Running pcre2posix test $withvalgrind"
$valgrind ./pcre2posix_test >teststdoutM 2>teststderrM
if [ $? -ne 0 ]; then
echo " "
echo "**** Test failed ****"
exit 1
fi
fi
if [ "$jit" -eq 0 ]; then
echo "Skipping JIT regression tests: JIT is not enabled"
elif [ "x$withebcdic" != x ]; then
echo "Skipping JIT regression tests: tests not supported on EBCDIC"
else
echo "Running JIT regression tests $withvalgrind"
$jrvalgrind ./pcre2_jit_test >teststdoutM 2>teststderrM
if [ $? -ne 0 -o -s teststderrM ]; then
echo " "
echo "**** Test failed ****"
cat teststderrM
cat teststdoutM
exit 1
fi
fi
}
# Update the total count whenever a new test is added; it is used to show
# progess as each test is run.
testtotal=`expr 17 \* $usemain + \
1 \* $usemain \* $usedebug + \
1 \* $usetmp + 1 \* $usetmpjit + \
1 \* $ISGCC \* $usemain + \
1 \* $ISGCC \* $usemain \* $useasan + \
1 \* $ISGCC \* $usemain \* $useusan + \
13 \* $usejit + \
2 \* $useebcdic + \
1 \* $useebcdicjit + \
2 \* $usemainvalgrind + \
2 \* $usejitvalgrind`
testcount=0
if [ $testtotal -eq 0 ] ; then
echo "** No tests selected"
exit 1
fi
valgrind=
jrvalgrind=
withvalgrind=
malloc=
withmalloc=
srcdir=.
export srcdir
if [ $usejit -ne 0 ]; then
enable_jit=--enable-jit
else
enable_jit=
fi
# If gcc is in use, run a maximally configured test with -O2, because that can
# throw up warnings that are not detected with -O0. Then run a second test with
# -fsanitize=address, which also may throw up new warnings as well as checking
# things at runtime. Finally, run another test using -fsanitize=undefined
# -std-gnu99 to check for runtime actions that are not well defined.
if [ $ISGCC -ne 0 -a $usemain -ne 0 ]; then
echo "---------- Maximally configured test with -O2 ----------"
SAVECFLAGS="$CFLAGS"
CFLAGS="-O2 $CFLAGS"
echo "CFLAGS=$CFLAGS"
opts="--disable-shared $enable_jit --enable-pcre2-16 --enable-pcre2-32"
runtest
if [ $useasan -ne 0 ]; then
echo "---------- Maximally configured test with -fsanitize=address ----------"
# Following a kernel change, sanitize address doesn't work unless the extra
# PIE options are also set.
CFLAGS="$OFLAGS $SAVECFLAGS -no-pie -fno-PIE -fsanitize=address"
echo "CFLAGS=$CFLAGS"
opts="--disable-shared $enable_jit --enable-pcre2-16 --enable-pcre2-32"
runtest
fi
# This also seems to be the case for sanitize undefined.
if [ $useusan -ne 0 ]; then
echo "------- Maximally configured test with -fsanitize=undefined -fno-sanitize=alignment -std=gnu99 -------"
CFLAGS="$OFLAGS $SAVECFLAGS -no-pie -fno-PIE -fsanitize=undefined -fno-sanitize=alignment -std=gnu99"
echo "CFLAGS=$CFLAGS"
opts="--disable-shared $enable_jit --enable-pcre2-16 --enable-pcre2-32"
runtest
fi
CFLAGS="$SAVECFLAGS"
fi
# This set of tests builds PCRE2 and runs the tests with a variety of configure
# options, in the current (source) directory. The empty configuration builds
# with all the default settings. As well as testing that these options work, we
# use --disable-shared or --disable-static except for the default test (which
# builds both) to save a bit of time by building only one version of the
# library for the subsequent tests.
echo "---------- CFLAGS for the remaining tests ----------"
CFLAGS="$OFLAGS $CFLAGS"
echo "CFLAGS=$CFLAGS"
if [ $usemain -ne 0 ]; then
if [ $usedebug -ne 0 ]; then
echo "---------- Maximally configured test with --enable-debug ----------"
opts="--disable-shared $enable_jit --enable-pcre2-16 --enable-pcre2-32 --enable-debug"
runtest
fi
echo "---------- Non-JIT tests in the current directory ----------"
for opts in \
"" \
"--disable-static" \
"--disable-shared" \
"--disable-unicode --disable-shared --enable-never-backslash-C" \
"--with-link-size=3 --disable-shared --disable-pcre2grep-callout" \
"--disable-unicode --enable-rebuild-chartables --disable-shared" \
"--disable-unicode --enable-newline-is-any --disable-shared" \
"--disable-unicode --enable-newline-is-cr --disable-shared" \
"--disable-unicode --enable-newline-is-crlf --disable-shared" \
"--disable-unicode --enable-newline-is-anycrlf --enable-bsr-anycrlf --disable-shared" \
"--enable-newline-is-any --disable-static" \
"--disable-unicode --enable-pcre2-16 --enable-debug" \
"--enable-pcre2-16 --disable-shared" \
"--disable-unicode --enable-pcre2-32" \
"--enable-pcre2-32 --disable-shared" \
"--disable-unicode --enable-pcre2-32 --enable-pcre2-16 --disable-shared" \
"--disable-unicode --enable-pcre2-32 --enable-pcre2-16 --disable-pcre2-8 --disable-shared"
do
runtest
done
fi
# Now run the JIT tests unless disabled
if [ $usejit -ne 0 ]; then
echo "---------- JIT tests in the current directory ----------"
for opts in \
"--disable-unicode --enable-jit --disable-shared" \
"--enable-jit --disable-shared" \
"--enable-jit --with-link-size=3 --disable-shared" \
"--enable-jit --enable-pcre2-16 --disable-shared" \
"--disable-unicode --enable-jit --enable-pcre2-16 --disable-pcre2-8 --disable-shared" \
"--enable-jit --enable-pcre2-16 --disable-pcre2-8 --disable-shared" \
"--enable-jit --enable-pcre2-16 --with-link-size=3 --disable-shared" \
"--enable-jit --enable-pcre2-16 --with-link-size=4 --disable-shared" \
"--enable-jit --enable-pcre2-32 --disable-shared" \
"--disable-unicode --enable-jit --enable-pcre2-32 --disable-pcre2-8 --disable-shared" \
"--enable-jit --enable-pcre2-32 --disable-pcre2-8 --disable-shared" \
"--enable-jit --enable-pcre2-32 --with-link-size=4 --disable-shared" \
"--enable-jit --enable-pcre2-32 --enable-pcre2-16 --disable-pcre2-8 --enable-newline-is-anycrlf --enable-bsr-anycrlf --disable-shared"
do
runtest
done
fi
# Now run some tests with EBCDIC enabled
if [ $useebcdic -ne 0 -o $useebcdicjit -ne 0 ]; then
echo "---------- EBCDIC tests in the current directory ----------"
withebcdic="with EBCDIC"
if [ $useebcdic -ne 0 ]; then
for opts in \
"--disable-unicode --enable-ebcdic --enable-ebcdic-ignoring-compiler" \
"--disable-unicode --enable-ebcdic --enable-ebcdic-ignoring-compiler --enable-ebcdic-nl25"
do
runtest
done
fi
if [ $useebcdicjit -ne 0 ]; then
for opts in \
"--disable-unicode --enable-jit --enable-ebcdic --enable-ebcdic-ignoring-compiler"
do
runtest
done
fi
fi
withebcdic=
# Now re-run some of the tests under valgrind.
if [ $usevalgrind -ne 0 ]; then
echo "---------- Tests in the current directory using valgrind ----------"
valgrind=valgrind
withvalgrind="with valgrind"
malloc=-malloc
withmalloc="with -malloc"
if [ $usemainvalgrind -ne 0 ]; then
for opts in \
"--disable-shared" \
"--with-link-size=3 --enable-pcre2-16 --enable-pcre2-32 --disable-shared"
do
opts="--enable-valgrind $opts"
runtest
# Only need to run the first test with -malloc.
malloc=
withmalloc=
done
fi
malloc=-malloc
withmalloc="with -malloc"
if [ $usejitvalgrind -ne 0 ]; then
jrvalgrind="valgrind --tool=memcheck -q --smc-check=all-non-file --suppressions=$srcdir/testdata/valgrind-jit.supp"
for opts in \
"--enable-jit --disable-shared" \
"--enable-jit --enable-pcre2-16 --enable-pcre2-32"
do
opts="--enable-valgrind $opts"
runtest
# Only need to run the first test with -malloc.
malloc=
withmalloc=
done
fi
fi
valgrind=
jrvalgrind=
withvalgrind=
malloc=
withmalloc=
# Clean up the distribution and then do at least one build and test in a
# directory other than the source directory. It doesn't work unless the
# source directory is cleaned up first.
if [ -f Makefile ]; then
echo "Running 'make distclean'"
make distclean >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "** 'make distclean' failed"
exit 1
fi
fi
echo "---------- End of tests in the source directory ----------"
echo "Removing teststdoutM and teststderrM"
rm -rf teststdoutM teststderrM
if [ $usetmp -ne 0 -o $usetmpjit -ne 0 ]; then
srcdir=`pwd`
export srcdir
if [ ! -e $tmp ]; then
mkdir $tmp
fi
if [ ! -d $tmp ]; then
echo "** Failed to create $tmp or it is not a directory"
exit 1
fi
cd $tmp
if [ $? -ne 0 ]; then
echo "** Failed to cd to $tmp"
exit 1
fi
if [ $usetmp -ne 0 ]; then
echo "---------- Tests in the $tmp directory ----------"
for opts in \
"--disable-shared"
do
runtest
done
fi
if [ $usetmpjit -ne 0 ]; then
echo "---------- JIT tests in the $tmp directory ----------"
for opts in \
"--enable-jit --disable-shared"
do
runtest
done
fi
echo "Removing $tmp"
rm -rf $tmp
fi
echo "---------- All done ----------"
# End