bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: c-stack and Irix - libsigsegv


From: Eric Blake
Subject: Re: c-stack and Irix - libsigsegv
Date: Sat, 20 Sep 2008 22:07:17 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.16) Gecko/20080708 Thunderbird/2.0.0.16 Mnenhy/0.7.5.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Eric Blake on 9/16/2008 4:50 PM:
> I've finally figured out why c-stack is being finicky on Irix 5.3 [1].  POSIX 
> requires that sigaltstack be given ss_sp pointing to the smallest address in 
> the alternate stack.  But Irix is non-compliant, and treats ss_sp as the 
> starting address of the stack (which, since it grows down, makes it the 
> largest 
> address in the stack).

Here's the minimal patch needed to CVS libsigsegv to expose the bug, as
well as work around it for Irix 5.3.  I still need to port something like
this for c-stack in the non-libsigsegv case.

2008-09-20  Eric Blake  <address@hidden>

        Detect and work around bug in Irix 5.3 sigaltstack.
        * m4/sigaltstack.m4 (SV_SIGALTSTACK): Test for broken stack
        direction in sigaltstack.
        * src/handler-unix.c (stackoverflow_install_handler): Adjust stack
        accordingly.
        * tests/stackoverflow1.c (stack_base): New variable.
        (check_stack_location): Additional check.
        (stackoverflow_handler, main): Use them to expose Irix bug.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkjVyHUACgkQ84KuGfSFAYCqfACffIR5b0vf+h21B7BAPtOxPPHW
/BgAniTKRbidmw4ocOIrS5qJnwik1Nj5
=EbMO
-----END PGP SIGNATURE-----
Index: src/handler-unix.c
===================================================================
RCS file: /sources/libsigsegv/libsigsegv/src/handler-unix.c,v
retrieving revision 1.8
diff -u -p -r1.8 handler-unix.c
--- src/handler-unix.c  24 Aug 2008 13:54:16 -0000      1.8
+++ src/handler-unix.c  21 Sep 2008 04:06:19 -0000
@@ -487,6 +487,11 @@ stackoverflow_install_handler (stackover
   {
     stack_t ss;
     ss.ss_sp = extra_stack;
+# if !SIGALTSTACK_LOW_BASE
+    /* Some platforms, such as Irix 5.3, mistakenly treat ss_sp as the
+       upper bound of the alternate stack.  */
+    ss.ss_sp += SIGSTKSZ - 1;
+# endif
     ss.ss_size = extra_stack_size;
     ss.ss_flags = 0; /* no SS_DISABLE */
     if (sigaltstack (&ss, (stack_t*)0) < 0)
Index: tests/stackoverflow1.c
===================================================================
RCS file: /sources/libsigsegv/libsigsegv/tests/stackoverflow1.c,v
retrieving revision 1.10
diff -u -p -r1.10 stackoverflow1.c
--- tests/stackoverflow1.c      24 Aug 2008 20:55:17 -0000      1.10
+++ tests/stackoverflow1.c      21 Sep 2008 04:06:19 -0000
@@ -49,6 +49,14 @@ jmp_buf mainloop;
 sigset_t mainsigset;
 
 volatile int pass = 0;
+volatile char *stack_base;
+
+static void
+check_stack_location (volatile char *addr)
+{
+  if (addr < stack_base || addr >= stack_base + SIGSTKSZ)
+    abort ();
+}
 
 static void
 stackoverflow_handler_continuation (void *arg1, void *arg2, void *arg3)
@@ -60,6 +68,11 @@ stackoverflow_handler_continuation (void
 void
 stackoverflow_handler (int emergency, stackoverflow_context_t scp)
 {
+  if (pass == 0)
+    {
+      char dummy;
+      check_stack_location (&dummy);
+    }
   pass++;
   printf ("Stack overflow %d caught.\n", pass);
   sigprocmask (SIG_SETMASK, &mainsigset, NULL);
@@ -99,6 +112,7 @@ main ()
 #endif
 
   /* Install the stack overflow handler.  */
+  stack_base = mystack;
   if (stackoverflow_install_handler (&stackoverflow_handler,
                                      mystack, sizeof (mystack))
       < 0)
Index: m4/sigaltstack.m4
===================================================================
RCS file: /sources/libsigsegv/libsigsegv/m4/sigaltstack.m4,v
retrieving revision 1.11
diff -u -p -r1.11 sigaltstack.m4
--- m4/sigaltstack.m4   24 Aug 2008 20:55:08 -0000      1.11
+++ m4/sigaltstack.m4   21 Sep 2008 04:06:19 -0000
@@ -1,4 +1,4 @@
-# sigaltstack.m4 serial 8 (libsigsegv-2.6)
+# sigaltstack.m4 serial 9 (libsigsegv-2.7)
 dnl Copyright (C) 2002-2006, 2008 Bruno Haible <address@hidden>
 dnl This file is free software, distributed under the terms of the GNU
 dnl General Public License.  As a special exception to the GNU General
@@ -123,5 +123,64 @@ int main ()
   if test "$sv_cv_sigaltstack" != no; then
     AC_DEFINE(HAVE_WORKING_SIGALTSTACK, 1,
       [Define if you have the sigaltstack() function and it works.])
+    AC_CACHE_CHECK([for correct sigaltstack boundary],
+      [sv_cv_sigaltstack_low_base], [
+      AC_RUN_IFELSE([
+        AC_LANG_SOURCE([[
+#include <stdlib.h>
+#include <signal.h>
+#if HAVE_SYS_SIGNAL_H
+# include <sys/signal.h>
+#endif
+#ifndef SIGSTKSZ
+# define SIGSTKSZ 16384
+#endif
+volatile char *stack_base;
+static void check_stack_location (volatile char *addr)
+{
+  if (addr >= stack_base && addr < stack_base + SIGSTKSZ)
+    exit (0);
+}
+void stackoverflow_handler (int sig)
+{
+  char dummy;
+  check_stack_location (&dummy);
+  exit (1);
+}
+int main ()
+{
+  char mystack[SIGSTKSZ];
+  stack_t altstack;
+  struct sigaction action;
+  /* Install the alternate stack.  */
+  stack_base = altstack.ss_sp = mystack;
+  altstack.ss_size = sizeof (mystack);
+  altstack.ss_flags = 0; /* no SS_DISABLE */
+  if (sigaltstack (&altstack, NULL) < 0)
+    exit (1);
+  /* Install the SIGSEGV handler.  */
+  sigemptyset (&action.sa_mask);
+  action.sa_handler = &stackoverflow_handler;
+  action.sa_flags = SA_ONSTACK;
+  sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
+  /* Provoke a SIGSEGV.  */
+  raise (SIGSEGV);
+  exit (2);
+}]])],
+      [sv_cv_sigaltstack_low_base=yes],
+      [sv_cv_sigaltstack_low_base=no],
+      [
+        dnl FIXME: Put in some more known values here.
+        case "$host_os" in
+          irix5*) sv_cv_sigaltstack_low_base="no" ;;
+          *)      sv_cv_sigaltstack_low_base="guessing yes" ;;
+        esac
+      ])
+    ])
+    if test "$sv_cv_sigaltstack_low_base" != no; then
+      AC_DEFINE([SIGALTSTACK_LOW_BASE], [1],
+        [Define if sigaltstack() obeys POSIX by interpreting the stack
+         base as the low address of a range, even if the stack grows down.])
+    fi
   fi
 ])

reply via email to

[Prev in Thread] Current Thread [Next in Thread]