From e8518b85c5171e6be83655283cce427583a054e1 Mon Sep 17 00:00:00 2001 From: "hp.com!davidm" Date: Wed, 13 Oct 2004 14:14:09 +0000 Subject: [PATCH] Ignore NULL stack-frames---they can't possibly be the correct target of a longjmp() because the caller of setjmp() must have a non-NULL frame. (Logical change 1.273) --- src/longjmp.c | 22 ++++++++++++++++++++++ src/siglongjmp.c | 36 +++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/longjmp.c b/src/longjmp.c index 33a9226b..f99e4785 100644 --- a/src/longjmp.c +++ b/src/longjmp.c @@ -70,6 +70,28 @@ _longjmp (jmp_buf env, int val) if (bsp != wp[JB_BSP]) continue; + + if (unlikely (sol == 0)) + { + unw_word_t prev_sp; + unw_cursor_t tmp = c; + + /* The caller of {sig,}setjmp() cannot have a NULL-frame. + If we see a NULL-frame, we haven't reached the right + target yet. To have a NULL-frame, the number of locals + must be zero and the stack-frame must also be + empty. */ + + if (unw_step (&tmp) < 0) + abort (); + + if (unw_get_reg (&tmp, UNW_REG_SP, &prev_sp) < 0) + abort (); + + if (sp == prev_sp) + /* got a NULL-frame; keep looking... */ + continue; + } } #endif diff --git a/src/siglongjmp.c b/src/siglongjmp.c index ac0483f0..3f8c9e2a 100644 --- a/src/siglongjmp.c +++ b/src/siglongjmp.c @@ -73,6 +73,28 @@ siglongjmp (sigjmp_buf env, int val) if (bsp != wp[JB_BSP]) continue; + + if (unlikely (sol == 0)) + { + unw_word_t prev_sp; + unw_cursor_t tmp = c; + + /* The caller of {sig,}setjmp() cannot have a NULL-frame. + If we see a NULL-frame, we haven't reached the right + target yet. To have a NULL-frame, the number of locals + must be zero and the stack-frame must also be + empty. */ + + if (unw_step (&tmp) < 0) + abort (); + + if (unw_get_reg (&tmp, UNW_REG_SP, &prev_sp) < 0) + abort (); + + if (sp == prev_sp) + /* got a NULL-frame; keep looking... */ + continue; + } } #endif @@ -84,13 +106,13 @@ siglongjmp (sigjmp_buf env, int val) cont = &_UI_longjmp_cont; #if UNW_TARGET_IA64 - /* On ia64 we cannot call sigprocmask() at _UI_siglongjmp_cont() - because the signal may have switched stacks and the old - stack's register-backing store may have overflown, leaving us - no space to allocate the stacked registers needed to call - sigprocmask(). Fortunately, we can just let unw_resume() - (via sigreturn) take care of restoring the signal-mask. - That's faster anyhow. + /* On ia64 we cannot always call sigprocmask() at + _UI_siglongjmp_cont() because the signal may have switched + stacks and the old stack's register-backing store may have + overflown, leaving us no space to allocate the stacked + registers needed to call sigprocmask(). Fortunately, we can + just let unw_resume() (via sigreturn) take care of restoring + the signal-mask. That's faster anyhow. XXX We probably should do the analogous on all architectures. */ if (((struct cursor *) &c)->sigcontext_addr)