summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2008-06-05 07:08:58 -0600
committerEric Blake <ebb9@byu.net>2008-08-07 07:15:42 -0600
commit07eba241aeaf090c0f2e8248ee8a6fe65d84795c (patch)
treeddcec859f3470b79bbd9a58c4c21c75a2b0a8d50
parent642c2a905e6979de747b9fa21a8f553a5885e7ae (diff)
downloadm4-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--ChangeLog22
-rw-r--r--NEWS3
-rw-r--r--configure.ac58
-rw-r--r--doc/m4.texinfo11
-rw-r--r--m4/gnulib-cache.m43
-rw-r--r--src/Makefile.am3
-rw-r--r--src/m4.c35
-rw-r--r--src/m4.h4
-rw-r--r--src/stackovf.c422
9 files changed, 43 insertions, 518 deletions
diff --git a/ChangeLog b/ChangeLog
index 4e196af0..8ce45459 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/NEWS b/NEWS
index 2a4ba93e..1014a917 100644
--- a/NEWS
+++ b/NEWS
@@ -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)
diff --git a/src/m4.c b/src/m4.c
index ca341cc8..880f13df 100644
--- a/src/m4.c
+++ b/src/m4.c
@@ -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. */
diff --git a/src/m4.h b/src/m4.h
index af3fd15d..929fd418 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -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 */
-
-}