diff options
Diffstat (limited to 'debug/tst-longjmp_chk.c')
-rw-r--r-- | debug/tst-longjmp_chk.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/debug/tst-longjmp_chk.c b/debug/tst-longjmp_chk.c new file mode 100644 index 0000000000..8892974cc7 --- /dev/null +++ b/debug/tst-longjmp_chk.c @@ -0,0 +1,86 @@ +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <setjmp.h> +#include <signal.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static jmp_buf b; + + +static void +__attribute__ ((noinline)) +f (void) +{ + char buf[1000]; + asm volatile ("" : "=m" (buf)); + + if (setjmp (b) != 0) + { + puts ("second longjmp succeeded"); + exit (1); + } +} + + +static bool expected_to_fail; + + +static void +handler (int sig) +{ + if (expected_to_fail) + _exit (0); + else + { + static const char msg[] = "unexpected longjmp failure\n"; + TEMP_FAILURE_RETRY (write (STDOUT_FILENO, msg, sizeof (msg) - 1)); + _exit (1); + } +} + + +int +main (void) +{ + struct sigaction sa; + sa.sa_handler = handler; + sa.sa_flags = 0; + sigemptyset (&sa.sa_mask); + + sigaction (SIGABRT, &sa, NULL); + + /* Avoid all the buffer overflow messages on stderr. */ + int fd = open (_PATH_DEVNULL, O_WRONLY); + if (fd == -1) + close (STDERR_FILENO); + else + { + dup2 (fd, STDERR_FILENO); + close (fd); + } + setenv ("LIBC_FATAL_STDERR_", "1", 1); + + + expected_to_fail = false; + + if (setjmp (b) == 0) + { + longjmp (b, 1); + /* NOTREACHED */ + printf ("first longjmp returned\n"); + return 1; + } + + + expected_to_fail = true; + + f (); + longjmp (b, 1); + + puts ("second longjmp returned"); + return 1; +} |