From c3699626dadc317196805e487b18e44cfe937cad Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 4 Apr 2014 08:37:25 +0000 Subject: signal.c: check stack overflow by SP * signal.c (check_stack_overflow): raise SystemStackError if SP register and fault address is in the same page, on x86 linux. [EXPERIMENTAL] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45517 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- signal.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'signal.c') diff --git a/signal.c b/signal.c index cdc36b58e6..0c173fa708 100644 --- a/signal.c +++ b/signal.c @@ -635,21 +635,41 @@ rb_get_next_signal(void) #if defined(USE_SIGALTSTACK) || defined(_WIN32) +NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th)); +#if defined __linux__ && (defined __i386__ || defined __x86_64__) +static void +check_stack_overflow(const uintptr_t addr, const ucontext_t *ctx) +{ +# if defined REG_RSP + const greg_t sp = ctx->uc_mcontext.gregs[REG_RSP]; +# else + const greg_t sp = ctx->uc_mcontext.gregs[REG_ESP]; +# endif + enum {pagesize = 4096}; + if ((uintptr_t)sp / pagesize == addr / pagesize) { + ruby_thread_stack_overflow(GET_THREAD()); + } +} +#else static void check_stack_overflow(const void *addr) { int ruby_stack_overflowed_p(const rb_thread_t *, const void *); - NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th)); rb_thread_t *th = GET_THREAD(); if (ruby_stack_overflowed_p(th, addr)) { ruby_thread_stack_overflow(th); } } +#endif #ifdef _WIN32 #define CHECK_STACK_OVERFLOW() check_stack_overflow(0) #else #define FAULT_ADDRESS info->si_addr -#define CHECK_STACK_OVERFLOW() check_stack_overflow(FAULT_ADDRESS) +#if defined __linux__ && (defined __i386__ || defined __x86_64__) +# define CHECK_STACK_OVERFLOW() check_stack_overflow((uintptr_t)FAULT_ADDRESS, ctx) +#else +# define CHECK_STACK_OVERFLOW() check_stack_overflow(FAULT_ADDRESS) +#endif #define MESSAGE_FAULT_ADDRESS " at %p", FAULT_ADDRESS #endif #else -- cgit v1.2.3