mirror of
https://https.git.savannah.gnu.org/git/gettext.git
synced 2026-01-26 15:39:11 +00:00
Avoid crash by SIGFPE during plural form expression evaluation.
Libraries (such as libintl and libgettextpo) should not raise signals, because catching such signals cannot be done in a multithread-safe way. * gettext-runtime/intl/plural-exp.h (enum eval_status): New enum items PE_INTDIV, PE_INTOVF. * gettext-runtime/intl/eval-plural.h (plural_eval_recurse): When a division argument is zero, return status PE_INTDIV instead of raising SIGFPE. * gettext-runtime/intl/dcigettext.c (INTDIV0_RAISES_SIGFPE): Remove macro. Don't include <signal.h>. * gettext-runtime/intl/configure.ac: Don't invoke gt_INTDIV0. * gettext-runtime/intl/m4/intdiv0.m4: Remove file. * gettext-runtime/intl/Makefile.am (ACLOCAL_AMFLAGS): Remove option '-I m4'. (EXTRA_DIST): Remove m4/intdiv0.m4. * autogen.sh: When invoking aclocal in gettext-runtime/intl, omit option '-I m4'. * gettext-tools/src/msgl-check.c: Don't include <setjmp.h>, <signal.h>. (plural_expression_histogram): Don't invoke install_sigfpe_handler, uninstall_sigfpe_handler. (check_plural_eval): Don't invoke setjmp, install_sigfpe_handler, uninstall_sigfpe_handler. Remove 'volatile' from array variable. Produce error message when status PE_INTDIV or PE_INTOVF occurred. * gettext-tools/src/plural-eval.h: Don't include <setjmp.h>. (sigjmp_buf, sigsetjmp, siglongjmp): Remove definitions. (USE_SIGINFO): Remove macro. (sigfpe_exit, sigfpe_code, install_sigfpe_handler, uninstall_sigfpe_handler): Remove declarations. * gettext-tools/src/plural-eval.c: Don't include <signal.h>. (sigfpe_exit, sigfpe_code): Remove variables. (sigfpe_handler, install_sigfpe_handler, uninstall_sigfpe_handler): Remove functions. * gettext-tools/configure.ac: Don't invoke gt_SIGINFO. * gettext-tools/m4/siginfo.m4: Remove file. * gettext-tools/m4/Makefile.am (EXTRA_DIST): Remove it.
This commit is contained in:
parent
429ba6c6b8
commit
726bfb1d1c
@ -438,7 +438,7 @@ dir0=`pwd`
|
||||
|
||||
echo "$0: generating configure in gettext-runtime/intl..."
|
||||
cd gettext-runtime/intl
|
||||
aclocal -I ../../m4 -I ../m4 -I m4 -I gnulib-m4 \
|
||||
aclocal -I ../../m4 -I ../m4 -I gnulib-m4 \
|
||||
&& autoconf \
|
||||
&& autoheader && touch config.h.in \
|
||||
&& touch ChangeLog \
|
||||
|
||||
@ -18,12 +18,11 @@
|
||||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
AUTOMAKE_OPTIONS = 1.10 gnu no-dependencies
|
||||
ACLOCAL_AMFLAGS = -I ../../m4 -I ../m4 -I m4 -I gnulib-m4
|
||||
ACLOCAL_AMFLAGS = -I ../../m4 -I ../m4 -I gnulib-m4
|
||||
|
||||
SUBDIRS = gnulib-lib
|
||||
|
||||
EXTRA_DIST = \
|
||||
m4/intdiv0.m4
|
||||
EXTRA_DIST =
|
||||
BUILT_SOURCES =
|
||||
MOSTLYCLEANFILES = core *.stackdump
|
||||
CLEANFILES =
|
||||
|
||||
@ -118,7 +118,6 @@ AC_C_INLINE
|
||||
AC_TYPE_SIZE_T
|
||||
AC_FUNC_ALLOCA
|
||||
AC_FUNC_MMAP
|
||||
gt_INTDIV0
|
||||
gl_LOCK
|
||||
|
||||
AC_LINK_IFELSE(
|
||||
|
||||
@ -69,20 +69,6 @@ extern int errno;
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
/* Guess whether integer division by zero raises signal SIGFPE.
|
||||
Set to 1 only if you know for sure. In case of doubt, set to 0. */
|
||||
# if defined __alpha__ || defined __arm__ || defined __i386__ \
|
||||
|| defined __m68k__ || defined __s390__
|
||||
# define INTDIV0_RAISES_SIGFPE 1
|
||||
# else
|
||||
# define INTDIV0_RAISES_SIGFPE 0
|
||||
# endif
|
||||
#endif
|
||||
#if !INTDIV0_RAISES_SIGFPE
|
||||
# include <signal.h>
|
||||
#endif
|
||||
|
||||
#if defined HAVE_SYS_PARAM_H || defined _LIBC
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
@ -117,16 +117,12 @@ plural_eval_recurse (const struct expression *pexp, unsigned long int n,
|
||||
case mult:
|
||||
return OK (leftarg.value * rightarg.value);
|
||||
case divide:
|
||||
#if !INTDIV0_RAISES_SIGFPE
|
||||
if (rightarg.value == 0)
|
||||
raise (SIGFPE);
|
||||
#endif
|
||||
return (struct eval_result) { .status = PE_INTDIV };
|
||||
return OK (leftarg.value / rightarg.value);
|
||||
case module:
|
||||
#if !INTDIV0_RAISES_SIGFPE
|
||||
if (rightarg.value == 0)
|
||||
raise (SIGFPE);
|
||||
#endif
|
||||
return (struct eval_result) { .status = PE_INTDIV };
|
||||
return OK (leftarg.value % rightarg.value);
|
||||
case plus:
|
||||
return OK (leftarg.value + rightarg.value);
|
||||
|
||||
@ -1,90 +0,0 @@
|
||||
# intdiv0.m4 serial 9 (gettext-0.21.1)
|
||||
dnl Copyright (C) 2002, 2007-2008, 2010-2020 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_DEFUN([gt_INTDIV0],
|
||||
[
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
|
||||
AC_CACHE_CHECK([whether integer division by zero raises SIGFPE],
|
||||
[gt_cv_int_divbyzero_sigfpe],
|
||||
[
|
||||
gt_cv_int_divbyzero_sigfpe=
|
||||
changequote(,)dnl
|
||||
case "$host_os" in
|
||||
macos* | darwin[6-9]* | darwin[1-9][0-9]*)
|
||||
# On Mac OS X 10.2 or newer, just assume the same as when cross-
|
||||
# compiling. If we were to perform the real test, 1 Crash Report
|
||||
# dialog window would pop up.
|
||||
case "$host_cpu" in
|
||||
i[34567]86 | x86_64)
|
||||
gt_cv_int_divbyzero_sigfpe="guessing yes" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
changequote([,])dnl
|
||||
if test -z "$gt_cv_int_divbyzero_sigfpe"; then
|
||||
AC_RUN_IFELSE(
|
||||
[AC_LANG_SOURCE([[
|
||||
#include <stdlib.h> /* for exit() */
|
||||
#include <signal.h>
|
||||
#if !(defined _WIN32 && !defined __CYGWIN__)
|
||||
#include <unistd.h> /* for _exit() */
|
||||
#endif
|
||||
|
||||
static void
|
||||
sigfpe_handler (int sig)
|
||||
{
|
||||
/* Exit with code 0 if SIGFPE, with code 1 if any other signal. */
|
||||
_exit (sig != SIGFPE);
|
||||
}
|
||||
|
||||
int x = 1;
|
||||
int y = 0;
|
||||
int z;
|
||||
int inan;
|
||||
|
||||
int main ()
|
||||
{
|
||||
signal (SIGFPE, sigfpe_handler);
|
||||
/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */
|
||||
#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP)
|
||||
signal (SIGTRAP, sigfpe_handler);
|
||||
#endif
|
||||
/* Linux/SPARC yields signal SIGILL. */
|
||||
#if defined (__sparc__) && defined (__linux__)
|
||||
signal (SIGILL, sigfpe_handler);
|
||||
#endif
|
||||
|
||||
z = x / y;
|
||||
inan = y / y;
|
||||
exit (2);
|
||||
}
|
||||
]])],
|
||||
[gt_cv_int_divbyzero_sigfpe=yes],
|
||||
[gt_cv_int_divbyzero_sigfpe=no],
|
||||
[
|
||||
# Guess based on the CPU.
|
||||
changequote(,)dnl
|
||||
case "$host_cpu" in
|
||||
alpha* | i[34567]86 | x86_64 | m68k | s390*)
|
||||
gt_cv_int_divbyzero_sigfpe="guessing yes";;
|
||||
*)
|
||||
gt_cv_int_divbyzero_sigfpe="guessing no";;
|
||||
esac
|
||||
changequote([,])dnl
|
||||
])
|
||||
fi
|
||||
])
|
||||
case "$gt_cv_int_divbyzero_sigfpe" in
|
||||
*yes) value=1 ;;
|
||||
*) value=0 ;;
|
||||
esac
|
||||
AC_DEFINE_UNQUOTED([INTDIV0_RAISES_SIGFPE], [$value],
|
||||
[Define if integer division by zero raises signal SIGFPE.])
|
||||
])
|
||||
@ -117,6 +117,8 @@ extern void EXTRACT_PLURAL_EXPRESSION (const char *nullentry,
|
||||
enum eval_status
|
||||
{
|
||||
PE_OK, /* Evaluation succeeded, produced a value */
|
||||
PE_INTDIV, /* Integer division by zero */
|
||||
PE_INTOVF, /* Integer overflow */
|
||||
PE_STACKOVF, /* Stack overflow */
|
||||
PE_ASSERT /* Assertion failure */
|
||||
};
|
||||
|
||||
@ -231,7 +231,6 @@ AC_TYPE_PID_T
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_CHECK_FUNCS([select])
|
||||
gt_SIGINFO
|
||||
|
||||
AC_C_BIGENDIAN([endianness=1], [endianness=0],
|
||||
[echo "AC-C-BIGENDIAN fails to work on your system." | sed -e 's,-,_,g' 1>&2
|
||||
|
||||
@ -46,5 +46,4 @@ EXTRA_DIST = \
|
||||
csharpexec-test.cs csharpexec-test.exe \
|
||||
exported.m4 \
|
||||
hostname.m4 \
|
||||
locale-de.m4 \
|
||||
siginfo.m4
|
||||
locale-de.m4
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
# siginfo.m4 serial 2 (gettext-0.21.1)
|
||||
dnl Copyright (C) 2001-2002, 2020 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# Determine how to determine the precise cause of a signal, for example
|
||||
# division by zero.
|
||||
# - SUSV2 and POSIX specify the use of sigaction with SA_SIGINFO and a member
|
||||
# void (*)(int sig, siginfo_t *info, void *context) sa_sigaction.
|
||||
# Linux (2.2.x and newer) and Solaris implement this.
|
||||
# Linux (2.4.x and newer) on i386, m68k, sparc, sparc64, ia64 actually
|
||||
# deliver FPE_INTDIV.
|
||||
# - Without SA_SIGINFO:
|
||||
# - Linux on m68k calls the handler as
|
||||
# void (*)(int sig, int code, struct sigcontext* scp).
|
||||
# For division by zero, code would be VEC_ZERODIV<<2.
|
||||
# - Linux on sparc calls the handler either as
|
||||
# void (*)(int sig, int code, struct sigcontext* scp),
|
||||
# code for division by zero would be SUBSIG_IDIVZERO, or as
|
||||
# void (*)(int sig, siginfo_t *info, void *context).
|
||||
# Which one depends on a process specific flag in the kernel.
|
||||
# - Linux on sparc64 always calls the handler as
|
||||
# void (*)(int sig, siginfo_t *info, void *context).
|
||||
# - FreeBSD on i386 calls the handler as
|
||||
# void (*)(int sig, int code, void* scp, char* addr).
|
||||
# For division by zero, code would be FPE_INTDIV.
|
||||
# - SunOS 4 calls the handler as
|
||||
# void (*)(int sig, int code, void* scp, char* addr).
|
||||
# - Solaris?
|
||||
# - Irix 5, OSF/1, AIX call the handler as
|
||||
# void (*)(int sig, int code, struct sigcontext *scp).
|
||||
# These are so many OS and CPU dependencies that we don't bother, and rely
|
||||
# only on SA_SIGINFO.
|
||||
AC_DEFUN([gt_SIGINFO],
|
||||
[
|
||||
AC_CACHE_CHECK([for signal handlers with siginfo_t], gt_cv_siginfo_t,
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <signal.h>]],
|
||||
[[struct sigaction action;
|
||||
siginfo_t info;
|
||||
action.sa_flags = SA_SIGINFO;
|
||||
action.sa_sigaction = (void *) 0;
|
||||
]])],
|
||||
[gt_cv_siginfo_t=yes],
|
||||
[gt_cv_siginfo_t=no])])
|
||||
if test $gt_cv_siginfo_t = yes; then
|
||||
AC_DEFINE([HAVE_SIGINFO], [1],
|
||||
[Define to 1 if <signal.h> defines the siginfo_t type and
|
||||
struct sigaction has the sa_sigaction member and the SA_SIGINFO flag.])
|
||||
fi
|
||||
])
|
||||
@ -23,8 +23,6 @@
|
||||
#include "msgl-check.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -69,9 +67,6 @@ plural_expression_histogram (const struct plural_distribution *self,
|
||||
unsigned long n;
|
||||
unsigned int count;
|
||||
|
||||
/* Protect against arithmetic exceptions. */
|
||||
install_sigfpe_handler ();
|
||||
|
||||
count = 0;
|
||||
for (n = min; n <= max; n++)
|
||||
{
|
||||
@ -81,9 +76,6 @@ plural_expression_histogram (const struct plural_distribution *self,
|
||||
count++;
|
||||
}
|
||||
|
||||
/* End of protection against arithmetic exceptions. */
|
||||
uninstall_sigfpe_handler ();
|
||||
|
||||
return count;
|
||||
}
|
||||
else
|
||||
@ -105,7 +97,7 @@ check_plural_eval (const struct expression *plural_expr,
|
||||
/* Do as if the plural formula assumes a value N infinitely often if it
|
||||
assumes it at least 5 times. */
|
||||
#define OFTEN 5
|
||||
unsigned char * volatile array;
|
||||
unsigned char *array;
|
||||
|
||||
/* Allocate a distribution array. */
|
||||
if (nplurals_value <= 100)
|
||||
@ -114,116 +106,69 @@ check_plural_eval (const struct expression *plural_expr,
|
||||
/* nplurals_value is nonsense. Don't risk an out-of-memory. */
|
||||
array = NULL;
|
||||
|
||||
if (sigsetjmp (sigfpe_exit, 1) == 0)
|
||||
unsigned long n;
|
||||
|
||||
for (n = 0; n <= 1000; n++)
|
||||
{
|
||||
unsigned long n;
|
||||
|
||||
/* Protect against arithmetic exceptions. */
|
||||
install_sigfpe_handler ();
|
||||
|
||||
for (n = 0; n <= 1000; n++)
|
||||
struct eval_result res = plural_eval (plural_expr, n);
|
||||
if (res.status != PE_OK)
|
||||
{
|
||||
struct eval_result res = plural_eval (plural_expr, n);
|
||||
if (res.status != PE_OK)
|
||||
{
|
||||
/* End of protection against arithmetic exceptions. */
|
||||
uninstall_sigfpe_handler ();
|
||||
if (res.status == PE_INTDIV)
|
||||
po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false,
|
||||
_("plural expression can produce division by zero"));
|
||||
else if (res.status == PE_INTOVF)
|
||||
po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false,
|
||||
_("plural expression can produce integer overflow"));
|
||||
else if (res.status == PE_STACKOVF)
|
||||
po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false,
|
||||
_("plural expression can produce stack overflow"));
|
||||
else
|
||||
/* Other res.status values should not occur. */
|
||||
abort ();
|
||||
|
||||
if (res.status == PE_STACKOVF)
|
||||
po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false,
|
||||
_("plural expression can produce stack overflow"));
|
||||
else
|
||||
/* Other res.status values should not occur. */
|
||||
abort ();
|
||||
|
||||
free (array);
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long val = res.value;
|
||||
|
||||
if ((long) val < 0)
|
||||
{
|
||||
/* End of protection against arithmetic exceptions. */
|
||||
uninstall_sigfpe_handler ();
|
||||
|
||||
po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false,
|
||||
_("plural expression can produce negative values"));
|
||||
free (array);
|
||||
return 1;
|
||||
}
|
||||
else if (val >= nplurals_value)
|
||||
{
|
||||
char *msg;
|
||||
|
||||
/* End of protection against arithmetic exceptions. */
|
||||
uninstall_sigfpe_handler ();
|
||||
|
||||
msg = xasprintf (_("nplurals = %lu but plural expression can produce values as large as %lu"),
|
||||
nplurals_value, val);
|
||||
po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, msg);
|
||||
free (msg);
|
||||
free (array);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (array != NULL && array[val] < OFTEN)
|
||||
array[val]++;
|
||||
free (array);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* End of protection against arithmetic exceptions. */
|
||||
uninstall_sigfpe_handler ();
|
||||
unsigned long val = res.value;
|
||||
|
||||
/* Normalize the array[val] statistics. */
|
||||
if (array != NULL)
|
||||
if ((long) val < 0)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
for (val = 0; val < nplurals_value; val++)
|
||||
array[val] = (array[val] == OFTEN ? 1 : 0);
|
||||
po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false,
|
||||
_("plural expression can produce negative values"));
|
||||
free (array);
|
||||
return 1;
|
||||
}
|
||||
else if (val >= nplurals_value)
|
||||
{
|
||||
char *msg =
|
||||
xasprintf (_("nplurals = %lu but plural expression can produce values as large as %lu"),
|
||||
nplurals_value, val);
|
||||
po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, msg);
|
||||
free (msg);
|
||||
free (array);
|
||||
return 1;
|
||||
}
|
||||
|
||||
distribution->expr = plural_expr;
|
||||
distribution->often = array;
|
||||
distribution->often_length = (array != NULL ? nplurals_value : 0);
|
||||
distribution->histogram = plural_expression_histogram;
|
||||
|
||||
return 0;
|
||||
if (array != NULL && array[val] < OFTEN)
|
||||
array[val]++;
|
||||
}
|
||||
else
|
||||
|
||||
/* Normalize the array[val] statistics. */
|
||||
if (array != NULL)
|
||||
{
|
||||
/* Caught an arithmetic exception. */
|
||||
const char *msg;
|
||||
unsigned long val;
|
||||
|
||||
/* End of protection against arithmetic exceptions. */
|
||||
uninstall_sigfpe_handler ();
|
||||
|
||||
#if USE_SIGINFO
|
||||
switch (sigfpe_code)
|
||||
#endif
|
||||
{
|
||||
#if USE_SIGINFO
|
||||
# ifdef FPE_INTDIV
|
||||
case FPE_INTDIV:
|
||||
msg = _("plural expression can produce division by zero");
|
||||
break;
|
||||
# endif
|
||||
# ifdef FPE_INTOVF
|
||||
case FPE_INTOVF:
|
||||
msg = _("plural expression can produce integer overflow");
|
||||
break;
|
||||
# endif
|
||||
default:
|
||||
#endif
|
||||
msg = _("plural expression can produce arithmetic exceptions, possibly division by zero");
|
||||
}
|
||||
|
||||
po_xerror (PO_SEVERITY_ERROR, header, NULL, 0, 0, false, msg);
|
||||
|
||||
free (array);
|
||||
|
||||
return 1;
|
||||
for (val = 0; val < nplurals_value; val++)
|
||||
array[val] = (array[val] == OFTEN ? 1 : 0);
|
||||
}
|
||||
|
||||
distribution->expr = plural_expr;
|
||||
distribution->often = array;
|
||||
distribution->often_length = (array != NULL ? nplurals_value : 0);
|
||||
distribution->histogram = plural_expression_histogram;
|
||||
|
||||
return 0;
|
||||
#undef OFTEN
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* Expression evaluation for plural form selection.
|
||||
Copyright (C) 2000-2003, 2005, 2019-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000-2023 Free Software Foundation, Inc.
|
||||
Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@ -23,7 +23,6 @@
|
||||
#include "plural-eval.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "plural-exp.h"
|
||||
|
||||
@ -33,67 +32,3 @@
|
||||
/* Include the expression evaluation code from libintl, this time with
|
||||
'extern' linkage. */
|
||||
#include "eval-plural.h"
|
||||
|
||||
|
||||
/* Exit point. Must be set before calling install_sigfpe_handler(). */
|
||||
sigjmp_buf sigfpe_exit;
|
||||
|
||||
#if USE_SIGINFO
|
||||
|
||||
/* Additional information that is set before sigfpe_exit is invoked. */
|
||||
int volatile sigfpe_code;
|
||||
|
||||
/* Signal handler called in case of arithmetic exception (e.g. division
|
||||
by zero) during plural_eval. */
|
||||
static _GL_ASYNC_SAFE void
|
||||
sigfpe_handler (int sig, siginfo_t *sip, void *scp)
|
||||
{
|
||||
sigfpe_code = sip->si_code;
|
||||
/* This handler is invoked on the thread that caused the SIGFPE, that is,
|
||||
the thread that is doing plural evaluation. Therefore it's OK to use
|
||||
siglongjmp. */
|
||||
siglongjmp (sigfpe_exit, 1);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Signal handler called in case of arithmetic exception (e.g. division
|
||||
by zero) during plural_eval. */
|
||||
static _GL_ASYNC_SAFE void
|
||||
sigfpe_handler (int sig)
|
||||
{
|
||||
/* This handler is invoked on the thread that caused the SIGFPE, that is,
|
||||
the thread that is doing plural evaluation. Therefore it's OK to use
|
||||
siglongjmp. */
|
||||
siglongjmp (sigfpe_exit, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
install_sigfpe_handler (void)
|
||||
{
|
||||
#if USE_SIGINFO
|
||||
struct sigaction action;
|
||||
action.sa_sigaction = sigfpe_handler;
|
||||
action.sa_flags = SA_SIGINFO;
|
||||
sigemptyset (&action.sa_mask);
|
||||
sigaction (SIGFPE, &action, (struct sigaction *) NULL);
|
||||
#else
|
||||
signal (SIGFPE, sigfpe_handler);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
uninstall_sigfpe_handler (void)
|
||||
{
|
||||
#if USE_SIGINFO
|
||||
struct sigaction action;
|
||||
action.sa_handler = SIG_DFL;
|
||||
action.sa_flags = 0;
|
||||
sigemptyset (&action.sa_mask);
|
||||
sigaction (SIGFPE, &action, (struct sigaction *) NULL);
|
||||
#else
|
||||
signal (SIGFPE, SIG_DFL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -24,44 +24,4 @@
|
||||
#include "plural-exp.h"
|
||||
|
||||
|
||||
/* Protection against signals during plural evaluation. */
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
/* Some platforms don't have the sigjmp_buf type in <setjmp.h>. */
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
/* Native Woe32 API. */
|
||||
# define sigjmp_buf jmp_buf
|
||||
# define sigsetjmp(env,savesigs) setjmp (env)
|
||||
# define siglongjmp longjmp
|
||||
#endif
|
||||
|
||||
/* We use siginfo to get precise information about the signal.
|
||||
But siginfo doesn't work on Irix 6.5 and on Cygwin 2005. */
|
||||
#if HAVE_SIGINFO && !defined (__sgi) && !defined (__CYGWIN__)
|
||||
# define USE_SIGINFO 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Exit point. Must be set before calling install_sigfpe_handler(). */
|
||||
extern sigjmp_buf sigfpe_exit;
|
||||
|
||||
#if USE_SIGINFO
|
||||
/* Additional information that is set before sigfpe_exit is invoked. */
|
||||
extern int volatile sigfpe_code;
|
||||
#endif
|
||||
|
||||
/* Protect against signals during plural evaluation. Must be called around
|
||||
calls to plural_eval(). Must be called in pairs. */
|
||||
extern void install_sigfpe_handler (void);
|
||||
extern void uninstall_sigfpe_handler (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _PLURAL_EVAL_H */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user