summaryrefslogtreecommitdiff
path: root/test/setjmp
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@uclibc-ng.org>2016-10-24 20:22:12 +0200
committerWaldemar Brodkorb <wbx@uclibc-ng.org>2016-10-24 20:22:12 +0200
commit7988979a722b4cdf287b2093956a76a3f19b9897 (patch)
treed35e251d0472ceca55a2eef61cff261c8ee68fab /test/setjmp
add uClibc-ng test directory
Diffstat (limited to 'test/setjmp')
-rw-r--r--test/setjmp/Makefile8
-rw-r--r--test/setjmp/Makefile.in0
-rw-r--r--test/setjmp/bug269-setjmp.c106
-rw-r--r--test/setjmp/jmpbug.c51
-rw-r--r--test/setjmp/sigjmpbug.c51
-rw-r--r--test/setjmp/tst-setjmp.c118
-rw-r--r--test/setjmp/tst-vfork-longjmp.c108
7 files changed, 442 insertions, 0 deletions
diff --git a/test/setjmp/Makefile b/test/setjmp/Makefile
new file mode 100644
index 0000000..6feab59
--- /dev/null
+++ b/test/setjmp/Makefile
@@ -0,0 +1,8 @@
+# uClibc setjmp tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+top_srcdir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/test/setjmp/Makefile.in b/test/setjmp/Makefile.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/setjmp/Makefile.in
diff --git a/test/setjmp/bug269-setjmp.c b/test/setjmp/bug269-setjmp.c
new file mode 100644
index 0000000..a9254a1
--- /dev/null
+++ b/test/setjmp/bug269-setjmp.c
@@ -0,0 +1,106 @@
+/* Copyright (C) 2004 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/>. */
+
+/* Test case for Bugzilla # 269 */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <stdlib.h>
+
+jmp_buf buf1;
+jmp_buf buf2;
+int *p;
+int n_x = 6;
+
+static int g_counter = 0;
+
+static int
+f (void)
+{
+ static int counter = 0;
+ static int way_point1 = 3;
+ static int way_point2 = 2;
+ int lose = 0;
+
+ if (setjmp (buf1) != 101)
+ {
+ int a[n_x]; /* reallocate stack space */
+ g_counter++;
+ p = &a[0];
+ if (g_counter < 5)
+ longjmp (buf1, 2);
+ else if (g_counter == 5)
+ longjmp (buf1, 101);
+ else
+ {
+ _setjmp (buf2);
+ _longjmp (buf1, 101);
+ }
+ }
+
+ way_point1--;
+
+ if (counter == 0)
+ {
+ counter++;
+ {
+ int a[n_x]; /* reallocate stack space */
+ g_counter++;
+ p = &a[0];
+ if (g_counter < 5)
+ longjmp (buf1, 2);
+ else if (g_counter == 5)
+ longjmp (buf1, 101);
+ else
+ {
+ _setjmp (buf2);
+ _longjmp (buf1, 101);
+ }
+ }
+ }
+
+ way_point2--;
+
+ if (counter == 1)
+ {
+ counter++;
+ longjmp (buf2, 2);
+ }
+
+ lose = !(way_point1 == 0 && way_point2 == 0
+ && g_counter == 6 && counter == 2);
+
+ return lose;
+}
+
+static int
+do_test (void)
+{
+ int lose;
+
+ lose = f ();
+
+ if (lose)
+ puts ("Test FAILED!");
+ else
+ puts ("Test succeeded!");
+
+ return lose ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/setjmp/jmpbug.c b/test/setjmp/jmpbug.c
new file mode 100644
index 0000000..da087a7
--- /dev/null
+++ b/test/setjmp/jmpbug.c
@@ -0,0 +1,51 @@
+/* setjmp vs alloca test case. Exercised bug on sparc. */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <alloca.h>
+
+int ret;
+int verbose;
+
+__attribute__ ((__noreturn__))
+static void
+sub5 (jmp_buf buf)
+{
+ longjmp (buf, 1);
+}
+
+static void
+test (int x)
+{
+ jmp_buf buf;
+ char *foo;
+ int arr[100];
+
+ ++ret;
+
+ arr[77] = x;
+ if (setjmp (buf))
+ {
+ --ret;
+ if (verbose)
+ printf ("made it ok; %d\n", arr[77]);
+ return;
+ }
+
+ foo = (char *) alloca (128);
+ sub5 (buf);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+
+ verbose = (argc != 1);
+ ret = 0;
+
+ for (i = 123; i < 345; ++i)
+ test (i);
+
+ return ret;
+}
diff --git a/test/setjmp/sigjmpbug.c b/test/setjmp/sigjmpbug.c
new file mode 100644
index 0000000..5b17181
--- /dev/null
+++ b/test/setjmp/sigjmpbug.c
@@ -0,0 +1,51 @@
+/* sigsetjmp vs alloca test case. Exercised bug on sparc. */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <alloca.h>
+
+int ret;
+int verbose;
+
+__attribute__ ((__noreturn__))
+static void
+sub5 (jmp_buf buf)
+{
+ siglongjmp (buf, 1);
+}
+
+static void
+test (int x)
+{
+ sigjmp_buf buf;
+ char *foo;
+ int arr[100];
+
+ ++ret;
+
+ arr[77] = x;
+ if (sigsetjmp (buf, 1))
+ {
+ --ret;
+ if (verbose)
+ printf ("made it ok; %d\n", arr[77]);
+ return;
+ }
+
+ foo = (char *) alloca (128);
+ sub5 (buf);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+
+ verbose = (argc != 1);
+ ret = 0;
+
+ for (i = 123; i < 345; ++i)
+ test (i);
+
+ return ret;
+}
diff --git a/test/setjmp/tst-setjmp.c b/test/setjmp/tst-setjmp.c
new file mode 100644
index 0000000..ea1c29a
--- /dev/null
+++ b/test/setjmp/tst-setjmp.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 1991, 1992, 1997, 1998, 2000 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 <stdio.h>
+#include <setjmp.h>
+#include <stdlib.h>
+
+static jmp_buf env;
+static int last_value = -1, lose = 0;
+
+__attribute__ ((__noreturn__))
+static void
+jump (int val)
+{
+ longjmp (env, val);
+}
+
+int
+main (void)
+{
+ int value;
+
+ value = setjmp (env);
+ if (value != last_value + 1)
+ {
+ fputs("Shouldn't have ", stdout);
+ lose = 1;
+ }
+ last_value = value;
+ switch (value)
+ {
+ case 0:
+ puts("Saved environment.");
+ jump (0);
+ default:
+ printf ("Jumped to %d.\n", value);
+ if (value < 10)
+ jump (value + 1);
+ }
+
+ if (!lose && value == 10)
+ {
+ /* Do a second test, this time without `setjmp' being a macro.
+ This is not required by ISO C but we have this for compatibility. */
+#undef setjmp
+ extern int setjmp (jmp_buf);
+
+ last_value = -1;
+ lose = 0;
+
+ value = setjmp (env);
+ if (value != last_value + 1)
+ {
+ fputs("Shouldn't have ", stdout);
+ lose = 1;
+ }
+ last_value = value;
+ switch (value)
+ {
+ case 0:
+ puts("Saved environment.");
+ jump (0);
+ default:
+ printf ("Jumped to %d.\n", value);
+ if (value < 10)
+ jump (value + 1);
+ }
+ }
+
+ if (!lose && value == 10)
+ {
+ /* And again for the `_setjmp' function. */
+#ifndef _setjmp
+ extern int _setjmp (jmp_buf);
+#endif
+ last_value = -1;
+ lose = 0;
+
+ value = _setjmp (env);
+ if (value != last_value + 1)
+ {
+ fputs("Shouldn't have ", stdout);
+ lose = 1;
+ }
+ last_value = value;
+ switch (value)
+ {
+ case 0:
+ puts("Saved environment.");
+ jump (0);
+ default:
+ printf ("Jumped to %d.\n", value);
+ if (value < 10)
+ jump (value + 1);
+ }
+ }
+
+ if (lose || value != 10)
+ puts ("Test FAILED!");
+ else
+ puts ("Test succeeded!");
+
+ return lose ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/test/setjmp/tst-vfork-longjmp.c b/test/setjmp/tst-vfork-longjmp.c
new file mode 100644
index 0000000..2784424
--- /dev/null
+++ b/test/setjmp/tst-vfork-longjmp.c
@@ -0,0 +1,108 @@
+/* make sure we can vfork/exec across setjmp/longjmp's
+ * and make sure signal block masks don't get corrupted
+ * in the process.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+
+int verbose = 0;
+
+static int execute_child(const char *prog)
+{
+ int status;
+ pid_t child;
+ child = vfork();
+ if (child == 0) {
+ execlp(prog, prog, NULL);
+ perror("Could not execute specified prog");
+ _exit(1);
+ } else if (child == 1)
+ return 1;
+ wait(&status);
+ return WEXITSTATUS(status);
+}
+
+sigset_t orig_mask;
+
+static int check_sig_mask(void)
+{
+ int status;
+ pid_t child;
+
+ child = vfork();
+ if (child == 0) {
+ int ret;
+ sigset_t child_mask;
+ memset(&child_mask, 0x00, sizeof(child_mask));
+ ret = sigprocmask(SIG_BLOCK, NULL, &child_mask);
+ if (ret != 0) {
+ perror("could not get child sig block mask");
+ _exit(1);
+ }
+ ret = memcmp(&orig_mask, &child_mask, sizeof(orig_mask));
+ if (verbose) {
+ printf("sigmsk: %08lx%08lx ", child_mask.__val[1], child_mask.__val[0]);
+ printf("sigmsk: %08lx%08lx ", orig_mask.__val[1], orig_mask.__val[0]);
+ printf("%i\n", ret);
+ }
+ _exit(ret);
+ } else if (child == 1)
+ return 1;
+ wait(&status);
+ return WEXITSTATUS(status);
+}
+
+int main(int argc, char *argv[])
+{
+ const char *prog;
+ jmp_buf env;
+ sigjmp_buf sigenv;
+ int max;
+ /* values modified between setjmp/longjmp cannot be local to this func */
+ static int cnt, ret;
+
+ memset(&orig_mask, 0x00, sizeof(orig_mask));
+ ret = sigprocmask(SIG_BLOCK, NULL, &orig_mask);
+ if (ret != 0) {
+ perror("could not get orig sig block mask");
+ return 1;
+ }
+
+ prog = (argc > 1 ? argv[1] : "true");
+ ret = 0;
+ verbose = 0;
+ max = 10;
+
+ /* test vfork()/exec() inside of sigsetjmp/siglongjmp */
+ cnt = 0;
+ sigsetjmp(sigenv, 1);
+ ++cnt;
+ if (verbose)
+ printf("sigsetjmp loop %i\n", cnt);
+ ret |= check_sig_mask();
+ ret |= execute_child(prog);
+ if (cnt < max)
+ siglongjmp(sigenv, 0);
+
+ /* test vfork()/sigprocmask() inside of setjmp/longjmp */
+ cnt = 0;
+ setjmp(env);
+ ++cnt;
+ if (verbose)
+ printf("setjmp loop %i\n", cnt);
+ ret |= check_sig_mask();
+ ret |= execute_child(prog);
+ if (cnt < max)
+ longjmp(env, 0);
+
+ return ret;
+}