diff options
Diffstat (limited to 'stdlib')
-rw-r--r-- | stdlib/Makefile | 9 | ||||
-rw-r--r-- | stdlib/tst-setcontext3.c | 138 | ||||
-rw-r--r-- | stdlib/tst-setcontext3.sh | 54 |
3 files changed, 200 insertions, 1 deletions
diff --git a/stdlib/Makefile b/stdlib/Makefile index c78fdb5..3300dd2 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -73,7 +73,8 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \ tst-makecontext3 bug-getcontext bug-fmtmsg1 \ tst-secure-getenv tst-strtod-overflow tst-strtod-round \ - tst-tininess tst-strtod-underflow tst-tls-atexit + tst-tininess tst-strtod-underflow tst-tls-atexit \ + tst-setcontext3 tests-static := tst-secure-getenv modules-names = tst-tls-atexit-lib @@ -157,3 +158,9 @@ tst-tls-atexit-lib.so-no-z-defs = yes $(objpfx)tst-tls-atexit: $(shared-thread-library) $(libdl) $(objpfx)tst-tls-atexit.out: $(objpfx)tst-tls-atexit-lib.so + +$(objpfx)tst-setcontext3.out: tst-setcontext3.sh $(objpfx)tst-setcontext3 + $(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \ + '$(run-program-env)' '$(test-program-prefix-after-env)' \ + $(common-objpfx)stdlib/; \ + $(evaluate-test) diff --git a/stdlib/tst-setcontext3.c b/stdlib/tst-setcontext3.c new file mode 100644 index 0000000..fda2128 --- /dev/null +++ b/stdlib/tst-setcontext3.c @@ -0,0 +1,138 @@ +/* Bug 18125: Verify setcontext calls exit() and not _exit(). + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ucontext.h> +#include <unistd.h> +#include <limits.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +/* Please note that depending on the outcome of Bug 18135 this test + may become invalid, and instead of testing for calling exit it + should be reworked to test for the last context calling + pthread_exit(). */ + +static ucontext_t ctx; +static char *filename; + +/* It is intended that this function does nothing. */ +static void +cf (void) +{ + printf ("called context function\n"); +} + +static void +exit_called (void) +{ + int fd; + ssize_t res; + const char buf[] = "Called exit function\n"; + + fd = open (filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + if (fd == -1) + { + printf ("FAIL: Unable to create test file %s\n", filename); + exit (1); + } + res = write (fd, buf, sizeof (buf)); + if (res != sizeof (buf)) + { + printf ("FAIL: Expected to write test file in one write call.\n"); + exit (1); + } + res = close (fd); + if (res == -1) + { + printf ("FAIL: Failed to close test file.\n"); + exit (1); + } + printf ("PASS: %s", buf); +} + +/* The test expects a filename given by the wrapper calling script. + The test then registers an atexit handler that will create the + file to indicate that the atexit handler ran. Then the test + creates a context, modifies it with makecontext, and sets it. + The context has only a single context which then must exit. + If it incorrectly exits via _exit then the atexit handler is + not run, the file is not created, and the wrapper detects this + and fails the test. This test cannot be done using an _exit + interposer since setcontext avoids the PLT and calls _exit + directly. */ +static int +do_test (int argc, char **argv) +{ + int ret; + char st1[32768]; + ucontext_t tempctx = ctx; + + if (argc < 2) + { + printf ("FAIL: Test missing filename argument.\n"); + exit (1); + } + + filename = argv[1]; + + atexit (exit_called); + + puts ("making contexts"); + if (getcontext (&ctx) != 0) + { + if (errno == ENOSYS) + { + /* Exit with 77 to mark the test as UNSUPPORTED. */ + printf ("UNSUPPORTED: getcontext not implemented.\n"); + exit (77); + } + + printf ("FAIL: getcontext failed.\n"); + exit (1); + } + + ctx.uc_stack.ss_sp = st1; + ctx.uc_stack.ss_size = sizeof (st1); + ctx.uc_link = 0; + makecontext (&ctx, cf, 0); + + /* Without this check, a stub makecontext can make us spin forever. */ + if (memcmp (&tempctx, &ctx, sizeof ctx) == 0) + { + puts ("UNSUPPORTED: makecontext was a no-op, presuming not implemented"); + exit (77); + } + + ret = setcontext (&ctx); + if (ret != 0) + { + printf ("FAIL: setcontext returned with %d and errno of %d.\n", ret, errno); + exit (1); + } + + printf ("FAIL: Impossibly returned to main.\n"); + exit (1); +} + +#include "../test-skeleton.c" diff --git a/stdlib/tst-setcontext3.sh b/stdlib/tst-setcontext3.sh new file mode 100644 index 0000000..6ad67a8 --- /dev/null +++ b/stdlib/tst-setcontext3.sh @@ -0,0 +1,54 @@ +#! /bin/bash +# Bug 18125: Test the exit functionality of setcontext(). +# Copyright (C) 2015 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +set -e + +common_objpfx=$1 +test_program_prefix_before_env=$2 +run_program_env=$3 +test_program_prefix_after_env=$4 +objpfx=$5 + +test_pre="${test_program_prefix_before_env} ${run_program_env}" +test="${test_program_prefix_after_env} ${objpfx}tst-setcontext3" +out=${objpfx}tst-setcontext3.out + +tempfiles=() +cleanup() { + rm -f "${tempfiles[@]}" +} +trap cleanup 0 + +tempfile=$(mktemp "tst-setcontext3.XXXXXXXXXX") +tempfiles+=("$tempfile") + +# We want to run the test program and see if secontext called +# exit() and wrote out the test file we specified. If the +# test exits with a non-zero status this will fail because we +# are using `set -e`. +$test_pre $test "$tempfile" + +# Look for resulting file. +if [ -e "$tempfile" ]; then + echo "PASS: tst-setcontext3 an exit() and created $tempfile" + exit 0 +else + echo "FAIL: tst-setcontext3 did not create $tempfile" + exit 1 +fi |