diff options
author | Eric Blake <ebb9@byu.net> | 2008-06-05 07:08:58 -0600 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2008-08-07 07:15:42 -0600 |
commit | 07eba241aeaf090c0f2e8248ee8a6fe65d84795c (patch) | |
tree | ddcec859f3470b79bbd9a58c4c21c75a2b0a8d50 | |
parent | 642c2a905e6979de747b9fa21a8f553a5885e7ae (diff) | |
download | m4-07eba241aeaf090c0f2e8248ee8a6fe65d84795c.tar.gz |
Replace stackovf with gnulib c-stack.
* m4/gnulib.cache.m4: Import c-stack module.
* configure.ac (AC_CHECK_HEADERS_ONCE): Remove check for
siginfo.h, sys/wait.h.
(AC_CHECK_TYPES): Likewise for siginfo_t.
(AC_CHECK_MEMBERS): Likewise for sa_sigaction, ss_sp.
(AC_CHECK_FUNCS_ONCE): Likewise for sigaction, sigaltstack,
sigstack, sigvec, strerror.
(M4_cv_use_stackovf): Likewise for stack overflow detection.
* src/Makefile.am (m4_SOURCES): Don't build stackovf.c.
* src/stackovf.c: Delete.
* src/m4.h (setup_stackovf_trap): Delete.
* src/m4.c (stackovf_handler): Delete.
(main): Use c_stack_action instead of setup_stackovf_trap. If
stack overflow is detectable, don't limit -L artificially.
(usage): Document unlimited default on supported systems.
* doc/m4.texinfo (Limits control): Document new default nesting
limit.
* NEWS: Document this change.
Signed-off-by: Eric Blake <ebb9@byu.net>
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | configure.ac | 58 | ||||
-rw-r--r-- | doc/m4.texinfo | 11 | ||||
-rw-r--r-- | m4/gnulib-cache.m4 | 3 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/m4.c | 35 | ||||
-rw-r--r-- | src/m4.h | 4 | ||||
-rw-r--r-- | src/stackovf.c | 422 |
9 files changed, 43 insertions, 518 deletions
@@ -1,3 +1,25 @@ +2008-06-06 Eric Blake <ebb9@byu.net> + + Replace stackovf with gnulib c-stack. + * m4/gnulib.cache.m4: Import c-stack module. + * configure.ac (AC_CHECK_HEADERS_ONCE): Remove check for + siginfo.h, sys/wait.h. + (AC_CHECK_TYPES): Likewise for siginfo_t. + (AC_CHECK_MEMBERS): Likewise for sa_sigaction, ss_sp. + (AC_CHECK_FUNCS_ONCE): Likewise for sigaction, sigaltstack, + sigstack, sigvec, strerror. + (M4_cv_use_stackovf): Likewise for stack overflow detection. + * src/Makefile.am (m4_SOURCES): Don't build stackovf.c. + * src/stackovf.c: Delete. + * src/m4.h (setup_stackovf_trap): Delete. + * src/m4.c (stackovf_handler): Delete. + (main): Use c_stack_action instead of setup_stackovf_trap. If + stack overflow is detectable, don't limit -L artificially. + (usage): Document unlimited default on supported systems. + * doc/m4.texinfo (Limits control): Document new default nesting + limit. + * NEWS: Document this change. + 2008-06-03 Eric Blake <ebb9@byu.net> Use progname module rather than rolling our own program_name. @@ -9,6 +9,9 @@ Foundation, Inc. a macro. This was most noticeable with `traceon(`traceon')', but would also happen in cases such as `foo(traceon(`foo'))'. +** The `-L'/`--nesting-limit' command-line option now defaults to 0 for + unlimited on platforms that can detect and deal with stack overflow. + ** A number of portability improvements inherited from gnulib. * Noteworthy changes in Version 1.4.11 (2008-04-02) [stable] diff --git a/configure.ac b/configure.ac index ea4e130c..3fb059b6 100644 --- a/configure.ac +++ b/configure.ac @@ -32,27 +32,8 @@ AC_CONFIG_HEADERS([lib/config.h:lib/config.hin]) AC_PROG_CC M4_EARLY -AC_CHECK_HEADERS_ONCE([siginfo.h sys/wait.h]) -AC_CHECK_TYPES([siginfo_t], [], [], -[[#include <signal.h> -#if HAVE_SIGINFO_H -# include <siginfo.h> -#endif -]]) -AC_CHECK_MEMBERS([struct sigaction.sa_sigaction], [], [], -[[#include <signal.h> -]]) -AC_CHECK_MEMBERS([stack_t.ss_sp], [], [], -[[#include <signal.h> -#if HAVE_SIGINFO_H -# include <siginfo.h> -#endif -]]) - AC_TYPE_SIGNAL -AC_CHECK_FUNCS_ONCE([sigaction sigaltstack sigstack sigvec strerror]) - # Tandem/NSK is broken - it has 'long long int' but not # 'unsigned long long int', which confuses assumptions made by gnulib. # Simply pretend that neither type exists if both do not work. @@ -67,45 +48,6 @@ fi M4_INIT -# Code from Jim Avera <jima@netcom.com>. -# stackovf.c requires: -# 1. Either sigaction with SA_ONSTACK, or sigvec with SV_ONSTACK -# 2. Either sigaltstack or sigstack -# 3. getrlimit, including support for RLIMIT_STACK -AC_CACHE_CHECK([if stack overflow is detectable], [M4_cv_use_stackovf], -[M4_cv_use_stackovf=no -if test "$ac_cv_func_sigaction" = yes || test "$ac_cv_func_sigvec" = yes; then - if test "$ac_cv_func_sigaltstack" = yes || test "$ac_cv_func_sigstack" = yes; then - AC_LINK_IFELSE([AC_LANG_PROGRAM([[ -#include <sys/time.h> -#include <sys/resource.h> -#include <signal.h> -]], [[struct rlimit r; getrlimit (RLIMIT_STACK, &r); -#if (!defined(HAVE_SIGACTION) || !defined(SA_ONSTACK)) \ - && (!defined(HAVE_SIGVEC) || !defined(SV_ONSTACK)) -choke me /* SA_ONSTACK and/or SV_ONSTACK are not defined */ -#endif -]])], [M4_cv_use_stackovf=yes]) - fi -fi]) -AM_CONDITIONAL([STACKOVF], [test "$M4_cv_use_stackovf" = yes]) -if test "$M4_cv_use_stackovf" = yes; then - AC_DEFINE([USE_STACKOVF], [1], - [Define to 1 if using stack overflow detection]) - AC_CHECK_TYPES([rlim_t], [], - [AC_DEFINE([rlim_t], [int], - [Define to int if rlim_t is not defined in sys/resource.h])], - [[#include <sys/resource.h> - ]]) - AC_CHECK_TYPES([stack_t], [], - [AC_DEFINE([stack_t], [struct sigaltstack], - [Define to struct sigaltstack if stack_t is not in signal.h])], - [[#include <signal.h> - ]]) - AC_CHECK_TYPES([sigcontext], [], [], [[#include <signal.h> - ]]) -fi - AC_CACHE_CHECK([if system() agrees with pclose()], [M4_cv_func_system_consistent], [AC_RUN_IFELSE([AC_LANG_PROGRAM([ diff --git a/doc/m4.texinfo b/doc/m4.texinfo index 00b9024d..f5b49d82 100644 --- a/doc/m4.texinfo +++ b/doc/m4.texinfo @@ -757,15 +757,16 @@ increase this value, unless you define an excessive number of macros. @cindex limit, nesting Artificially limit the nesting of macro calls to @var{NUM} levels, stopping program execution if this limit is ever exceeded. When not -specified, nesting is limited to 1024 levels. A value of zero means +specified, nesting defaults to unlimited on platforms that can detect +stack overflow, and to 1024 levels otherwise. A value of zero means unlimited; but then heavily nested code could potentially cause a stack overflow. -The precise effect of this option might be more correctly associated +The precise effect of this option is more correctly associated with textual nesting than dynamic recursion. It has been useful -when some complex @code{m4} input was generated by mechanical means. -Most users would never need this option. If shown to be obtrusive, -this option (which is still experimental) might well disappear. +when some complex @code{m4} input was generated by mechanical means, and +also in diagnosing recursive algorithms that do not scale well. +Most users never need to change this option from its default. @cindex rescanning This option does @emph{not} have the ability to break endless diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 352b70d1..c653c93d 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --local-dir=local --lib=libm4 --source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=build-aux --with-tests --no-libtool --macro-prefix=M4 announce-gen assert autobuild avltree-oset binary-io clean-temp cloexec close-stream closein config-h error fdl fflush fopen-safer fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops mkstemp obstack progname regex stdbool stdint stdlib-safer strstr strtod strtol unlocked-io verror version-etc version-etc-fsf xalloc xprintf xvasprintf-posix +# gnulib-tool --import --dir=. --local-dir=local --lib=libm4 --source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=build-aux --with-tests --no-libtool --macro-prefix=M4 announce-gen assert autobuild avltree-oset binary-io c-stack clean-temp cloexec close-stream closein config-h error fdl fflush fopen-safer fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops mkstemp obstack progname regex stdbool stdint stdlib-safer strstr strtod strtol unlocked-io verror version-etc version-etc-fsf xalloc xprintf xvasprintf-posix # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([local]) @@ -25,6 +25,7 @@ gl_MODULES([ autobuild avltree-oset binary-io + c-stack clean-temp cloexec close-stream diff --git a/src/Makefile.am b/src/Makefile.am index f2c15244..900f8ea6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,4 @@ AM_CPPFLAGS = -I$(top_srcdir)/lib -I../lib bin_PROGRAMS = m4 m4_SOURCES = m4.h m4.c builtin.c debug.c eval.c format.c freeze.c input.c \ macro.c output.c path.c symtab.c -if STACKOVF -m4_SOURCES += stackovf.c -endif m4_LDADD = ../lib/libm4.a $(LIBM4_LIBDEPS) $(POW_LIB) @@ -1,7 +1,7 @@ /* GNU m4 -- A simple macro processor - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006, 2007 - Free Software Foundation, Inc. + Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006, + 2007, 2008 Free Software Foundation, Inc. This file is part of GNU M4. @@ -25,6 +25,7 @@ #include <limits.h> #include <signal.h> +#include "c-stack.h" #include "progname.h" #include "version-etc.h" @@ -110,21 +111,6 @@ m4_error_at_line (int status, int errnum, const char *file, int line, if (fatal_warnings && ! retcode) retcode = EXIT_FAILURE; } - -#ifdef USE_STACKOVF - -/*---------------------------------------. -| Tell user stack overflowed and abort. | -`---------------------------------------*/ - -static void -stackovf_handler (void) -{ - M4ERROR ((EXIT_FAILURE, 0, - "ERROR: stack overflow. (Infinite define recursion?)")); -} - -#endif /* USE_STACKOV */ /*---------------------------------------------. @@ -175,15 +161,15 @@ Preprocessor features:\n\ -s, --synclines generate `#line NUM \"FILE\"' lines\n\ -U, --undefine=NAME undefine NAME\n\ ", stdout); - fputs ("\ -\n\ + puts (""); + xprintf (_("\ Limits control:\n\ -G, --traditional suppress all GNU extensions\n\ -H, --hashsize=PRIME set symbol lookup hash table size [509]\n\ - -L, --nesting-limit=NUMBER change artificial nesting limit [1024]\n\ -", stdout); + -L, --nesting-limit=NUMBER change nesting limit, 0 for unlimited [%d]\n\ +"), nesting_limit); + puts (""); fputs ("\ -\n\ Frozen state files:\n\ -F, --freeze-state=FILE produce a frozen state on FILE at end\n\ -R, --reload-state=FILE reload a frozen state from FILE at start\n\ @@ -338,9 +324,8 @@ main (int argc, char *const *argv, char *const *envp) include_init (); debug_init (); -#ifdef USE_STACKOVF - setup_stackovf_trap (argv, envp, stackovf_handler); -#endif + if (c_stack_action (NULL) == 0) + nesting_limit = 0; /* First, we decode the arguments, to size up tables and stuff. */ @@ -139,10 +139,6 @@ void m4_error_at_line (int, int, const char *, int, #define M4ERROR(Arglist) (m4_error Arglist) #define M4ERROR_AT_LINE(Arglist) (m4_error_at_line Arglist) -#ifdef USE_STACKOVF -void setup_stackovf_trap (char *const *, char *const *, - void (*handler) (void)); -#endif /* File: debug.c --- debugging and tracing function. */ diff --git a/src/stackovf.c b/src/stackovf.c deleted file mode 100644 index 3877cd9d..00000000 --- a/src/stackovf.c +++ /dev/null @@ -1,422 +0,0 @@ -/* Detect stack overflow (when getrlimit and sigaction or sigvec are available) - - Copyright (C) 1993, 1994, 2006, 2007 Free Software Foundation, Inc. - Jim Avera <jima@netcom.com>, October 1993. - - This file is part of GNU M4. - - GNU M4 is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - GNU M4 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* Compiled only when USE_STACKOVF is defined, which itself requires - getrlimit with the RLIMIT_STACK option, and support for alternate - signal stacks using either SVR4 or BSD interfaces. - - This should compile on ANY system which supports either sigaltstack() - or sigstack(), with or without <siginfo.h> or another way to determine - the fault address. - - There is no completely portable way to determine if a SIGSEGV signal - indicates a stack overflow. The fault address can be used to infer - this. However, the fault address is passed to the signal handler in - different ways on various systems. One of three methods are used to - determine the fault address: - - 1. The siginfo parameter (with siginfo.h, i.e., SVR4). - - 2. 4th "addr" parameter (assumed if struct sigcontext is defined, - i.e., SunOS 4.x/BSD). - - 3. None (if no method is available). This case just prints a - message before aborting with a core dump. That way the user at - least knows that it *might* be a recursion problem. - - Jim Avera <jima@netcom.com> writes, on Tue, 5 Oct 93 19:27 PDT: - - "I got interested finding out how a program could catch and - diagnose its own stack overflow, and ended up modifying m4 to do - this. Now it prints a nice error message and exits. - - How it works: SIGSEGV is caught using a separate signal stack. The - signal handler declares a stack overflow if the fault address is - near the end of the stack region, or if the maximum VM address - space limit has been reached. Otherwise, it returns to re-execute - the instruction with SIG_DFL set, so that any real bugs cause a - core dump as usual." - - Jim Avera <jima@netcom.com> writes, on Fri, 24 Jun 94 12:14 PDT: - - "The stack-overflow detection code would still be needed to avoid a - SIGSEGV abort if swap space was exhausted at the moment the stack - tried to grow. This is probably unlikely to occur with the - explicit nesting limit option of GNU m4." - - Jim Avera <jima@netcom.com> writes, on Wed, 6 Jul 1994 14:41 PDT: - - "When a stack overflow occurs, a SIGSEGV signal is sent, which by - default aborts the process with a core dump. - - The code in stackovf.c catches SIGSEGV using a separate signal - stack. The signal handler determines whether or not the SIGSEGV - arose from a stack overflow. If it is a stack overflow, an - external function is called (which, in m4, prints a message an - exits). Otherwise the SIGSEGV represents an m4 bug, and the signal - is re-raised with SIG_DFL set, which results in an abort and core - dump in the usual way. It seems important (to me) that internal m4 - bugs not be reported as user recursion errors, or vice-versa." */ - -#include "m4.h" /* stdlib.h, xmalloc() */ - -#include <assert.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <signal.h> - -#if HAVE_SIGINFO_H -# include <siginfo.h> -#endif - -#ifndef SA_RESETHAND -# define SA_RESETHAND 0 -#endif -#ifndef SA_SIGINFO -# define SA_SIGINFO 0 -#endif - -#ifndef SIGSTKSZ -# define SIGSTKSZ 8192 -#endif - -/* If the trap address is within STACKOVF_DETECT bytes of the calculated - stack limit, we diagnose a stack overflow. This must be large enough - to cover errors in our estimatation of the limit address, and to - account for the maximum size of local variables (the amount the - trapping reference might exceed the stack limit). Also, some machines - may report an arbitrary address within the same page frame. - If the value is too large, we might call some other SIGSEGV a stack - overflow, masking a bug. */ - -#ifndef STACKOVF_DETECT -# define STACKOVF_DETECT 16384 -#endif - -typedef void (*handler_t) (void); - -static const char *stackbot; -static const char *stackend; -static const char *arg0; -static handler_t stackovf_handler; - -/* The following OS-independent procedure is called from the SIGSEGV - signal handler. The signal handler obtains information about the trap - in an OS-dependent manner, and passes a parameter with the meanings as - explained below. - - If the OS explicitly identifies a stack overflow trap, either pass - PARAM_STACKOVF if a stack overflow, or pass PARAM_NOSTACKOVF if not - (id est, it is a random bounds violation). Otherwise, if the fault - address is available, pass the fault address. Otherwise (if no - information is available), pass NULL. - - Not given an explicit indication, we compare the fault address with - the estimated stack limit, and test to see if overall VM space is - exhausted. - - If a stack overflow is identified, then the external *stackovf_handler - function is called, which should print an error message and exit. If - it is NOT a stack overflow, then we silently abort with a core dump by - returning to re-raise the SIGSEGV with SIG_DFL set. If indeterminate, - then we do not call *stackovf_handler, but instead print an ambiguous - message and abort with a core dump. This only occurs on systems which - provide no information, but is better than nothing. */ - -#define PARAM_STACKOVF ((const char *) (1 + STACKOVF_DETECT)) -#define PARAM_NOSTACKOVF ((const char *) (2 + STACKOVF_DETECT)) - -static void -process_sigsegv (int signo, const char *p) -{ - long diff; - diff = (p - stackend); - -#ifdef DEBUG_STKOVF - { - char buf[140]; - - snprintf (buf, sizeof buf, - "process_sigsegv: p=%#lx stackend=%#lx diff=%ld bot=%#lx\n", - (long) p, (long) stackend, (long) diff, (long) stackbot); - write (2, buf, strlen (buf)); - } -#endif - - if (p != PARAM_NOSTACKOVF) - { - if ((long) sbrk (8192) == (long) -1) - { - - /* sbrk failed. Assume the RLIMIT_VMEM prevents expansion even - if the stack limit has not been reached. */ - - write (2, "VMEM limit exceeded?\n", 21); - p = PARAM_STACKOVF; - } - if (diff >= -STACKOVF_DETECT && diff <= STACKOVF_DETECT) - { - - /* The fault address is "sufficiently close" to the stack lim. */ - - p = PARAM_STACKOVF; - } - if (p == PARAM_STACKOVF) - { - - /* We have determined that this is indeed a stack overflow. */ - - (*stackovf_handler) (); /* should call exit() */ - } - } - if (p == NULL) - { - const char *cp; - - cp = "\ -Memory bounds violation detected (SIGSEGV). Either a stack overflow\n\ -occurred, or there is a bug in "; - write (2, cp, strlen (cp)); - write (2, arg0, strlen (arg0)); - cp = ". Check for possible infinite recursion.\n"; - write (2, cp, strlen (cp)); - } - - /* Return to re-execute the instruction which caused the trap with - SIGSEGV set to SIG_DFL. An abort with core dump should occur. */ - - signal (signo, SIG_DFL); -} - -#if HAVE_STRUCT_SIGACTION_SA_SIGACTION - -/* POSIX. */ - -static void -sigsegv_handler (int signo, siginfo_t *ip, void *context) -{ - process_sigsegv - (signo, (ip != NULL - && ip->si_signo == SIGSEGV ? (char *) ip->si_addr : NULL)); -} - -#elif HAVE_SIGINFO_T - -/* SVR4. */ - -static void -sigsegv_handler (int signo, siginfo_t *ip) -{ - process_sigsegv - (signo, (ip != NULL - && ip->si_signo == SIGSEGV ? (char *) ip->si_addr : NULL)); -} - -#elif HAVE_SIGCONTEXT - -/* SunOS 4.x (and BSD?). (not tested) */ - -static void -sigsegv_handler (int signo, int code, struct sigcontext *scp, char *addr) -{ - process_sigsegv (signo, addr); -} - -#else /* not HAVE_SIGCONTEXT */ - -/* OS provides no information. */ - -static void -sigsegv_handler (int signo) -{ - process_sigsegv (signo, NULL); -} - -#endif /* not HAVE_SIGCONTEXT */ - -/* Arrange to trap a stack-overflow and call a specified handler. The - call is on a dedicated signal stack. - - argv and envp are as passed to main(). - - If a stack overflow is not detected, then the SIGSEGV is re-raised - with action set to SIG_DFL, causing an abort and coredump in the usual - way. - - Detection of a stack overflow depends on the trap address being near - the stack limit address. The stack limit can not be directly - determined in a portable way, but we make an estimate based on the - address of the argv and environment vectors, their contents, and the - maximum stack size obtained using getrlimit. */ - -void -setup_stackovf_trap (char *const *argv, char *const *envp, handler_t handler) -{ - struct rlimit rl; - rlim_t stack_len; - int grows_upward; - register char *const *v; - register char *p; -#if HAVE_SIGACTION && defined SA_ONSTACK - struct sigaction act; -#elif HAVE_SIGVEC && defined SV_ONSTACK - struct sigvec vec; -#else - -Error - Do not know how to set up stack-ovf trap handler... - -#endif - - arg0 = argv[0]; - stackovf_handler = handler; - - /* Calculate the approximate expected addr for a stack-ovf trap. */ - - if (getrlimit (RLIMIT_STACK, &rl) < 0) - error (EXIT_FAILURE, errno, "getrlimit"); - stack_len = (rl.rlim_cur < rl.rlim_max ? rl.rlim_cur : rl.rlim_max); - stackbot = (char *) argv; - grows_upward = ((char *) &stack_len > stackbot); - if (grows_upward) - { - - /* Grows toward increasing addresses. */ - - for (v = argv; (p = (char *) *v) != NULL; v++) - { - if (p < stackbot) - stackbot = p; - } - if ((char *) envp < stackbot) - stackbot = (char *) envp; - for (v = envp; (p = (char *) *v) != NULL; v++) - { - if (p < stackbot) - stackbot = p; - } - stackend = stackbot + stack_len; - } - else - { - - /* The stack grows "downward" (toward decreasing addresses). */ - - for (v = argv; (p = (char *) *v) != NULL; v++) - { - if (p > stackbot) - stackbot = p; - } - if ((char *) envp > stackbot) - stackbot = (char *) envp; - for (v = envp; (p = (char *) *v) != NULL; v++) - { - if (p > stackbot) - stackbot = p; - } - stackend = stackbot - stack_len; - } - - /* Allocate a separate signal-handler stack. */ - -#if HAVE_SIGALTSTACK && (HAVE_SIGINFO_T || ! HAVE_SIGSTACK) - - /* Use sigaltstack only if siginfo_t is available, unless there is no - choice. */ - - { - stack_t ss; -# ifndef HAVE_STACK_T_SS_SP - /* This workaround is for BSD/OS 4.0.1: - http://lists.gnu.org/archive/html/bug-m4/2006-12/msg00004.html */ -# define ss_sp ss_base -# endif - - ss.ss_size = SIGSTKSZ; - ss.ss_sp = xmalloc ((unsigned) ss.ss_size); - ss.ss_flags = 0; - if (sigaltstack (&ss, NULL) < 0) - { - /* Oops - sigaltstack exists but doesn't work. We can't - install the overflow detector, but should gracefully treat - it as though sigaltstack doesn't exist. For example, this - happens when compiled with Linux 2.1 headers but run - against Linux 2.0 kernel. */ - free (ss.ss_sp); - if (errno == ENOSYS) - return; - error (EXIT_FAILURE, errno, "sigaltstack"); - } - } - -#elif HAVE_SIGSTACK - - { - struct sigstack ss; - char *stackbuf = xmalloc (2 * SIGSTKSZ); - - ss.ss_sp = stackbuf + SIGSTKSZ; - ss.ss_onstack = 0; - if (sigstack (&ss, NULL) < 0) - { - /* Oops - sigstack exists but doesn't work. We can't install - the overflow detector, but should gracefully treat it as - though sigstack doesn't exist. For example, this happens - when compiled with Linux 2.1 headers but run against Linux - 2.0 kernel. */ - free (stackbuf); - if (errno == ENOSYS) - return; - error (EXIT_FAILURE, errno, "sigstack"); - } - } - -#else /* not HAVE_SIGSTACK */ - -Error - Do not know how to set up stack-ovf trap handler... - -#endif /* not HAVE_SIGSTACK */ - - /* Arm the SIGSEGV signal handler. */ - -#if HAVE_SIGACTION && defined SA_ONSTACK - - sigaction (SIGSEGV, NULL, &act); -# if HAVE_STRUCT_SIGACTION_SA_SIGACTION - act.sa_sigaction = sigsegv_handler; -# else /* ! HAVE_STRUCT_SIGACTION_SA_SIGACTION */ - act.sa_handler = (RETSIGTYPE (*) (int)) sigsegv_handler; -# endif /* ! HAVE_STRUCT_SIGACTION_SA_SIGACTION */ - sigemptyset (&act.sa_mask); - act.sa_flags = (SA_ONSTACK | SA_RESETHAND | SA_SIGINFO); - if (sigaction (SIGSEGV, &act, NULL) < 0) - error (EXIT_FAILURE, errno, "sigaction"); - -#else /* ! HAVE_SIGACTION */ - - vec.sv_handler = (RETSIGTYPE (*) (int)) sigsegv_handler; - vec.sv_mask = 0; - vec.sv_flags = (SV_ONSTACK | SV_RESETHAND); - if (sigvec (SIGSEGV, &vec, NULL) < 0) - error (EXIT_FAILURE, errno, "sigvec"); - -#endif /* ! HAVE_SIGACTION */ - -} |