[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
stackovf: optionally use libsigsegv
From: |
Eric Blake |
Subject: |
stackovf: optionally use libsigsegv |
Date: |
Thu, 17 Jul 2008 22:17:56 +0000 (UTC) |
User-agent: |
Loom/3.14 (http://gmane.org/) |
I'm committing this on the stackovf branch. This completes the original goal I
had when setting out to create the branch: stack overflow detection in m4 is no
longer the unsafe portability nightmare it used to be. If you install the
optional library libsigsegv, this branch guarantees that on most modern porting
targets, stack overflow no longer causes a core dump (cygwin, mingw) nor is an
internal bug misdiagnosed as stack overflow (BSD, Linux, ...) (but we don't
have any internal bugs, right?). If you are lucky enough to have a platform
that does this without libsigsegv (Solaris), more power to you. Hopefully,
with the recent email on the Austin Group list, I can convince the lkml mailing
list that Linux is buggy for reporting the wrong uc_stack information on stack
overflow
As with any good patch series, I enhanced the test suite; the file
stackovf.test is cribbed from the master branch, but heavily tweaked to avoid
perl, to obey modern portable shell practices (I hope), and to fit within the
branch-1.6 non-Automake-based testsuite paradigm.
I also revived the DEBUG_STKOVF macro, which was deleted earlier in the branch,
such that I can build a debug version and intentionally crash m4 by exporting
M4_CRASH in the environment.
Next step - figure out how to make the master branch have two simultaneous
gnulib checkouts (the c-stack, strsignal, and related modules are not needed
for libm4.a, just the final m4 executable). Then I can merge this into both
branch-1.6 and master.
From: Eric Blake <address@hidden>
Date: Thu, 17 Jul 2008 12:00:49 -0600
Subject: [PATCH] Adjust to c-stack changes in gnulib.
* src/Makefile.am (m4_LDADD): Use libsigsegv when available and
necessary, via LIBCSTACK.
* src/m4.c (main) [DEBUG_STACKOVF]: Make it easier to test fault
handlers.
* checks/stackovf.test: New file.
* checks/Makefile.in (CHECKS): Add stackovf.test, and factor...
(DOC_CHECKS): ...generated documentation tests into new macro.
(DISTFILES): Distribute stackovf.test.
* checks/check-them: Special-case stackovf.test.
* NEWS: Enhance the NEWS item for -L improvements.
* README: Mention the optional dependency.
* HACKING: Mention maintenance burden added by libsigsegv.
Signed-off-by: Eric Blake <address@hidden>
---
ChangeLog | 16 ++++++++
HACKING | 7 ++++
NEWS | 7 +++-
README | 9 +++++
checks/Makefile.in | 12 ++++---
checks/check-them | 12 ++++++
checks/stackovf.test | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/Makefile.am | 2 +-
src/m4.c | 16 ++++++++
9 files changed, 173 insertions(+), 7 deletions(-)
create mode 100755 checks/stackovf.test
diff --git a/ChangeLog b/ChangeLog
index c51d171..e182a2b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2008-07-17 Eric Blake <address@hidden>
+
+ Adjust to c-stack changes in gnulib.
+ * src/Makefile.am (m4_LDADD): Use libsigsegv when available and
+ necessary, via LIBCSTACK.
+ * src/m4.c (main) [DEBUG_STACKOVF]: Make it easier to test fault
+ handlers.
+ * checks/stackovf.test: New file.
+ * checks/Makefile.in (CHECKS): Add stackovf.test, and factor...
+ (DOC_CHECKS): ...generated documentation tests into new macro.
+ (DISTFILES): Distribute stackovf.test.
+ * checks/check-them: Special-case stackovf.test.
+ * NEWS: Enhance the NEWS item for -L improvements.
+ * README: Mention the optional dependency.
+ * HACKING: Mention maintenance burden added by libsigsegv.
+
2008-06-23 Eric Blake <address@hidden>
Adjust to new gnulib-tool layout.
diff --git a/HACKING b/HACKING
index fd8cd1e..e127494 100644
--- a/HACKING
+++ b/HACKING
@@ -62,6 +62,13 @@ and is not part of a release distribution.
Note that none of these bootstrapping dependencies should be required
by a distributed release.
+* M4 has an optional build dependency. In order to ensure that the
+ dependency remains optional, you can avoid the library by using
+ `./configure --without-libsigsegv-prefix'. In order to ensure that
+ the dependency is still viable with the current code base, you should
+ install:
+ - Libsigsegv 2.5 or later
+
* Either add the gnulib directory to your PATH, or run
GNULIB_TOOL=path/to/gnulib/gnulib-tool ./bootstrap
diff --git a/NEWS b/NEWS
index 5aae856..bfda4d4 100644
--- a/NEWS
+++ b/NEWS
@@ -38,7 +38,12 @@ Foundation, Inc.
http://git.sv.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=56d42fa71
** The `-L'/`--nesting-limit' command-line option now defaults to 0 for
- unlimited on platforms that can detect and deal with stack overflow.
+ unlimited on platforms that can detect and deal with stack overflow. On
+ systems that lack alternate stack support, such as Cygwin, and on
+ systems that do not obey the POSIX semantics for distinguishing stack
+ overflow from other exceptions, such as Linux, you can optionally
+ install the libsigsegv library to enhance m4's ability to accurately
+ report stack overflow: http://www.gnu.org/software/libsigsegv/
** The `defn' builtin now warns when operating on an undefined macro name.
To simulate 1.4.x behavior, use:
diff --git a/README b/README
index 548ffb9..ea5061f 100644
--- a/README
+++ b/README
@@ -19,6 +19,15 @@ ahead and start with `./configure'. If you are trying to
build `m4'
from git or CVS, more information can be found in the file HACKING,
only found in a version control checkout.
+M4 has an optional dependency on the libsigsegv library:
+ http://www.gnu.org/software/libsigsegv/
+If the library has not been installed in the standard location, you
+can use `./configure --with-libsigsegv-prefix=/path/to/dir', to make
+the build of `m4' use /path/to/dir/include/sigsegv.h as appropriate.
+The use of this library is optional; the only difference in having it
+available is that it increases the number of platforms where `m4' can
+correctly distinguish stack overflow from an internal bug.
+
In the subdirectory `examples' you will find various m4 files, ranging
from trivial test files to rather advanced macros. If you intend to
use m4 seriously, you might find useful material down there.
diff --git a/checks/Makefile.in b/checks/Makefile.in
index 0e1091e..c43c2cc 100644
--- a/checks/Makefile.in
+++ b/checks/Makefile.in
@@ -36,14 +36,16 @@ program_transform_name = @program_transform_name@
AWK = @AWK@
# Vern says that the first star is required around an Alpha make bug.
-CHECKS = $(srcdir)/*[0-9][0-9][0-9].*
+DOC_CHECKS = $(srcdir)/*[0-9][0-9][0-9].*
+CHECKS = $(DOC_CHECKS) $(srcdir)/stackovf.test
# Makefile.in is automatically distributed by automake.
-DISTFILES = $(srcdir)/get-them $(srcdir)/check-them $(srcdir)/stamp-checks
+DISTFILES = $(srcdir)/get-them $(srcdir)/check-them $(srcdir)/stamp-checks \
+ $(srcdir)/stackovf.test
all: $(srcdir)/stamp-checks
$(srcdir)/stamp-checks: $(srcdir)/get-them $(srcdir)/../doc/m4.texinfo
- rm -f $(CHECKS)
+ rm -f $(DOC_CHECKS)
cd $(srcdir) && AWK=$(AWK) ./get-them ../doc/m4.texinfo
touch $(srcdir)/stamp-checks
@@ -73,13 +75,13 @@ distclean: clean
rm -f Makefile
maintainer-clean realclean: distclean
- rm -f $(CHECKS) $(srcdir)/stamp-checks
+ rm -f $(DOC_CHECKS) $(srcdir)/stamp-checks
distdir: dist
dist: $(DISTFILES)
@echo "Copying distribution files"
- @for file in $(DISTFILES) $(CHECKS); do \
+ @for file in $(DISTFILES) $(DOC_CHECKS); do \
ln $$file ../$(PACKAGE)-$(VERSION)/checks 2> /dev/null \
|| cp -p $$file ../$(PACKAGE)-$(VERSION)/checks; \
done
diff --git a/checks/check-them b/checks/check-them
index 7fba1d6..f66322b 100755
--- a/checks/check-them
+++ b/checks/check-them
@@ -70,6 +70,18 @@ do
continue
}
echo "Checking $file"
+
+ case $file in
+ *stackovf.test)
+ "$file" "$m4"
+ case $? in
+ 77) skipped="$skipped $file";;
+ 0) ;;
+ *) failed="$failed $file"
+ esac
+ continue ;;
+ esac
+
options=`sed -ne '3s/^dnl @ extra options: //p;3q' "$file"`
sed -e '/^dnl @/d' -e '/^\^D$/q' "$file" \
| LC_MESSAGES=C M4PATH=$examples "$m4" -d $options - >$out 2>$err
diff --git a/checks/stackovf.test b/checks/stackovf.test
new file mode 100755
index 0000000..78c3340
--- /dev/null
+++ b/checks/stackovf.test
@@ -0,0 +1,99 @@
+#!/bin/sh
+# This file is part of the GNU m4 testsuite
+# Copyright (C) 2000, 2003, 2007, 2008 Free Software Foundation, Inc.
+#
+# 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/>.
+
+# Script to verify that stack overflow is diagnosed properly when
+# there is infinite macro call nesting, provided the OS supports it.
+
+m4="$1"
+
+# Skip this test if -L defaults to 1024 instead of 0, as that is our
+# indicator that the OS does not support stack overflow detection.
+("$m4" --help | grep 'nesting.*\[0\]') >/dev/null 2>&1 \
+ || {
+ echo "$0: skipping test, no stack overflow support detected in $m4"
+ exit 77
+ }
+
+# On some systems the ulimit command is available in ksh or bash but not sh
+(exec 2>/dev/null; ulimit -Ss 300) || {
+ for altshell in bash bsh ksh zsh ; do
+ if (exec >/dev/null 2>&1; $altshell -c 'ulimit -Ss 300') && test -z "$2"
+ then
+ echo "Using $altshell because it supports ulimit"
+ exec $altshell "$0" "$@" running-with-$altshell
+ exit 1
+ fi
+ done
+}
+
+tmpdir=
+trap 'st=$?; rm -rf "$tmpdir" && exit $st' 0
+trap '(exit $?); exit $?' 1 2 3 15
+
+# Create a temporary subdirectory $tmpdir in $TMPDIR (default /tmp).
+# Use mktemp if possible; otherwise fall back on mkdir,
+# with $RANDOM to make collisions less likely.
+: ${TMPDIR=/tmp}
+{
+ tmpdir=`
+ (umask 077 && mktemp -d "$TMPDIR/m4stk-XXXXXX") 2>/dev/null
+ ` &&
+ test -n "$tmpdir" && test -d "$tmpdir"
+} || {
+ tmpdir=$TMPDIR/m4stk-$$-$RANDOM
+ (umask 077 && mkdir "$tmpdir")
+} || exit $?
+tmpfile="$tmpdir"/m4.out
+
+# Limit the stack size if the shell we are running permits it
+if (exec 2>/dev/null; ulimit -Ss 50)
+then
+ ulimit -Ss 50
+ echo "Stack soft limit set to `ulimit -s`K";
+else
+ echo "Can't reset stack limit - this may take a while..."
+fi
+
+# Induce stack overflow.
+echo 'define(a,a(a))a' | "$m4" > "$tmpfile" 2>&1
+result=$?
+
+exitcode=1
+if test $result -eq 0 ; then
+ echo "Failure - $m4 did not abort"
+else
+ # See if stack overflow was diagnosed.
+ case `cat "$tmpfile"` in
+ *stack\ overflow*)
+ case `echo "$tmpdir"/*` in
+ $tmpfile)
+ echo "Pass"
+ exitcode=0 ;;
+ *) echo "Failure - $m4 created unexpected core dump"
+ ls -l "$tmpdir" ;;
+ esac ;;
+ *) echo "Failure - $m4 aborted unexpectedly";
+ ;;
+ esac
+fi
+
+test $exitcode = 0 ||
+ { echo "Output from $m4:"; cat $tmpfile; }
+
+exit $exitcode
diff --git a/src/Makefile.am b/src/Makefile.am
index 900f8ea..80b9acf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,4 +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
-m4_LDADD = ../lib/libm4.a $(LIBM4_LIBDEPS) $(POW_LIB)
+m4_LDADD = ../lib/libm4.a $(LIBM4_LIBDEPS) $(POW_LIB) $(LIBCSTACK)
diff --git a/src/m4.c b/src/m4.c
index 970aa8b..a24f82d 100644
--- a/src/m4.c
+++ b/src/m4.c
@@ -488,6 +488,22 @@ main (int argc, char *const *argv, char *const *envp)
sigaction (SIGFPE, &act, NULL);
sigaction (SIGBUS, &act, NULL);
+#ifdef DEBUG_STKOVF
+ /* Make it easier to test our fault handlers. Exporting M4_CRASH=0
+ attempts a SIGSEGV, exporting it as 1 attempts an assertion
+ failure with a fallback to abort. */
+ {
+ char *crash = getenv ("M4_CRASH");
+ if (crash)
+ {
+ if (!atoi (crash))
+ ++*(int *) 8;
+ assert (false);
+ abort ();
+ }
+ }
+#endif /* DEBUG_STKOVF */
+
/* First, we decode the arguments, to size up tables and stuff. */
head = tail = NULL;
--
1.5.6
- stackovf: optionally use libsigsegv,
Eric Blake <=