From f02162a25b8b3f8c6addad57ee2fb4f3e87b4a4f Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Thu, 17 Dec 2009 13:56:12 -0800 Subject: [PATCH] Extensions/libraries/plugins might enable FPU/SSE2 exceptions, causing floating-point operations to crash (533035, r=robarnold,bsmedberg). --- toolkit/xre/Makefile.in | 5 +- toolkit/xre/nsAppRunner.cpp | 8 +- toolkit/xre/nsSigHandlers.cpp | 136 +++++++++++++++++++++++++++++++++- toolkit/xre/nsSigHandlers.h | 72 ++++++++++++++++++ 4 files changed, 208 insertions(+), 13 deletions(-) create mode 100644 toolkit/xre/nsSigHandlers.h diff --git a/toolkit/xre/Makefile.in b/toolkit/xre/Makefile.in index eab29087bd4..f7e4ea25e44 100644 --- a/toolkit/xre/Makefile.in +++ b/toolkit/xre/Makefile.in @@ -67,6 +67,7 @@ CPPSRCS = \ nsXREDirProvider.cpp \ nsNativeAppSupportBase.cpp \ nsAppData.cpp \ + nsSigHandlers.cpp \ $(NULL) ifdef MOZ_SPLASHSCREEN @@ -120,10 +121,6 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) CMMSRCS += MacApplicationDelegate.mm endif -ifneq (,$(filter-out OS2 WINNT,$(OS_ARCH))) -CPPSRCS += nsSigHandlers.cpp -endif - SHARED_LIBRARY_LIBS += ../profile/src/$(LIB_PREFIX)profile_s.$(LIB_SUFFIX) ifdef MOZ_ENABLE_XREMOTE diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 0b4f245851c..d7d7ec058c1 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -239,9 +239,7 @@ protected: }; #endif -#if defined(XP_UNIX) || defined(XP_BEOS) - extern void InstallUnixSignalHandlers(const char *ProgramName); -#endif +extern void InstallSignalHandlers(const char *ProgramName); #define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini") @@ -2678,9 +2676,7 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) #endif #endif -#if defined(XP_UNIX) || defined(XP_BEOS) - InstallUnixSignalHandlers(argv[0]); -#endif + InstallSignalHandlers(argv[0]); #ifdef MOZ_ACCESSIBILITY_ATK // Reset GTK_MODULES, strip atk-bridge if exists diff --git a/toolkit/xre/nsSigHandlers.cpp b/toolkit/xre/nsSigHandlers.cpp index 05386a185b5..027a5493d75 100644 --- a/toolkit/xre/nsSigHandlers.cpp +++ b/toolkit/xre/nsSigHandlers.cpp @@ -42,6 +42,10 @@ * platforms that do not support it. */ +#include "nsSigHandlers.h" + +#ifdef XP_UNIX + #include #include #include @@ -55,6 +59,7 @@ #include #include #include // atoi +#include #endif #if defined(SOLARIS) @@ -204,7 +209,53 @@ my_glib_log_func(const gchar *log_domain, GLogLevelFlags log_level, #endif -void InstallUnixSignalHandlers(const char *ProgramName) +static void fpehandler(int signum, siginfo_t *si, void *context) +{ +#ifdef XP_MACOSX + ucontext_t *uc = (ucontext_t *)context; + +#if defined(__i386__) || defined(__amd64__) + _STRUCT_FP_CONTROL *ctrl = &uc->uc_mcontext->__fs.__fpu_fcw; + ctrl->__invalid = ctrl->__denorm = ctrl->__zdiv = ctrl->__ovrfl = ctrl->__undfl = ctrl->__precis = 1; + + _STRUCT_FP_STATUS *status = &uc->uc_mcontext->__fs.__fpu_fsw; + status->__invalid = status->__denorm = status->__zdiv = status->__ovrfl = status->__undfl = + status->__precis = status->__stkflt = status->__errsumm = 0; + + __uint32_t *mxcsr = &uc->uc_mcontext->__fs.__fpu_mxcsr; + *mxcsr |= SSE_EXCEPTION_MASK; /* disable all SSE exceptions */ + *mxcsr &= ~SSE_STATUS_FLAGS; /* clear all pending SSE exceptions */ +#endif +#endif +#ifdef LINUX + ucontext_t *uc = (ucontext_t *)context; + +#if defined(__i386__) + /* + * It seems that we have no access to mxcsr on Linux. libc + * seems to be translating cw/sw to mxcsr. + */ + unsigned long int *cw = &uc->uc_mcontext.fpregs->cw; + *cw |= FPU_EXCEPTION_MASK; + + unsigned long int *sw = &uc->uc_mcontext.fpregs->sw; + *sw &= ~FPU_STATUS_FLAGS; +#endif +#if defined(__amd64__) + uint16_t *cw = &uc->uc_mcontext.fpregs->cwd; + *cwd |= FPU_EXCEPTION_MASK; + + uint16_t *sw = &uc->uc_mcontext.fpregs->swd; + *swd &= ~FPU_STATUS_FLAGS; + + __uint32_t *mxcsr = &uc->uc_mcontext->fpregs->mxcsr; + *mxcsr |= SSE_EXCEPTION_MASK; /* disable all SSE exceptions */ + *mxcsr &= ~SSE_STATUS_FLAGS; /* clear all pending SSE exceptions */ +#endif +#endif +} + +void InstallSignalHandlers(const char *ProgramName) { PL_strncpy(_progname,ProgramName, (sizeof(_progname)-1) ); @@ -226,15 +277,19 @@ void InstallUnixSignalHandlers(const char *ProgramName) signal(SIGSEGV, abnormal_exit_handler); signal(SIGILL, abnormal_exit_handler); signal(SIGABRT, abnormal_exit_handler); - signal(SIGFPE, abnormal_exit_handler); #elif defined(CRAWL_STACK_ON_SIGSEGV) signal(SIGSEGV, ah_crap_handler); signal(SIGILL, ah_crap_handler); signal(SIGABRT, ah_crap_handler); - signal(SIGFPE, ah_crap_handler); #endif // CRAWL_STACK_ON_SIGSEGV + /* Install a handler for floating point exceptions and disable them if they occur. */ + struct sigaction sa, osa; + sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO; + sa.sa_sigaction = fpehandler; + sigaction(SIGFPE, &sa, &osa); + #if defined(DEBUG) && defined(LINUX) const char *memLimit = PR_GetEnv("MOZ_MEM_LIMIT"); if (memLimit && *memLimit) @@ -289,3 +344,78 @@ void InstallUnixSignalHandlers(const char *ProgramName) } #endif } + +#elif XP_WIN + +#include + +#ifdef _M_IX86 +/* + * WinNT.h prior to SDK7 does not expose the structure of the ExtendedRegisters for ia86. + * We known that MxCsr is at offset 0x18 and is a DWORD. + */ +#define MXCSR(ctx) (*(DWORD *)(((BYTE *)(ctx)->ExtendedRegisters) + 0x18)) +#endif + +#ifdef _M_X64 +#define MXCSR(ctx) (ctx)->MxCsr +#endif + +#if defined(_M_IA32) || define(_M_X64) + +#define X87CW(ctx) (ctx)->FloatSave.ControlWord +#define X87SW(ctx) (ctx)->FloatSave.StatusWord + +/* + * SSE traps raise these exception codes, which are defined in internal NT headers + * but not winbase.h + */ +#define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4 +#define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5 + +LONG __stdcall FpeHandler(PEXCEPTION_POINTERS pe) +{ + PEXCEPTION_RECORD e = (PEXCEPTION_RECORD)pe->ExceptionRecord; + CONTEXT *c = (CONTEXT*)pe->ContextRecord; + + switch (e->ExceptionCode) { + case STATUS_FLOAT_DENORMAL_OPERAND: + case STATUS_FLOAT_DIVIDE_BY_ZERO: + case STATUS_FLOAT_INEXACT_RESULT: + case STATUS_FLOAT_INVALID_OPERATION: + case STATUS_FLOAT_OVERFLOW: + case STATUS_FLOAT_STACK_CHECK: + case STATUS_FLOAT_UNDERFLOW: + case STATUS_FLOAT_MULTIPLE_FAULTS: + case STATUS_FLOAT_MULTIPLE_TRAPS: + X87CW(c) |= FPU_EXCEPTION_MASK; /* disable all FPU exceptions */ + X86SW(c) &= ~FPU_STATUS_FLAGS; /* clear all pending FPU exceptions */ +#ifdef _M_IA32 + if (c->ContextFlags & CONTEXT_EXTENDED_REGISTERS) { +#endif + MXCSR(c) |= SSE_EXCEPTION_MASK; /* disable all SSE exceptions */ + MXCSR(c) &= ~SSE_STATUS_FLAGS; /* clear all pending SSE exceptions */ +#ifdef _M_IA32 + } +#endif + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +void InstallSignalHandlers(const char *ProgramName) +{ + SetUnhandledExceptionFilter(FpeHandler); +} + +#else + +void InstallSignalHandlers(const char *ProgramName) +{ +} + +#endif + +#else +#error No signal handling implementation for this platform. +#endif diff --git a/toolkit/xre/nsSigHandlers.h b/toolkit/xre/nsSigHandlers.h new file mode 100644 index 00000000000..4b02e974976 --- /dev/null +++ b/toolkit/xre/nsSigHandlers.h @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Corp + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Andreas Gal + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#if defined(_M_IA32) || defined(_M_X86) || defined(__i386__) || defined(__amd64__) + +/* + * x87 FPU Control Word: + * + * 0 -> IM Invalid Operation + * 1 -> DM Denormalized Operand + * 2 -> ZM Zero Divide + * 3 -> OM Overflow + * 4 -> UM Underflow + * 5 -> PM Precision + */ +#define FPU_EXCEPTION_MASK 0x3f + +/* + * x86 FPU Status Word: + * + * 0..5 -> Exception flags (see x86 FPU Control Word) + * 6 -> SF Stack Fault + * 7 -> ES Error Summary Status + */ +#define FPU_STATUS_FLAGS 0xff + +/* + * MXCSR Control and Status Register: + * + * 0..5 -> Exception flags (see x86 FPU Control Word) + * 6 -> DAZ Denormals Are Zero + * 7..12 -> Exception mask (see x86 FPU Control Word) + */ +#define SSE_STATUS_FLAGS FPU_EXCEPTION_MASK +#define SSE_EXCEPTION_MASK (FPU_EXCEPTION_MASK << 7) + +#endif