summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2011-03-19 21:29:16 +0000
committerDavid Mitchell <davem@iabyn.com>2011-03-19 22:03:40 +0000
commit9a7f166c9e80e6dce5b942cb7af5fc213e0466d4 (patch)
treec614aac028847948e8ea2e13cef9c3ee4df49727
parent55fa63f5f326538bec794ff6b165abff1ea07579 (diff)
downloadperl-9a7f166c9e80e6dce5b942cb7af5fc213e0466d4.tar.gz
In signal handler, don't inc stack pointers
In Perl_sighandler, we currently increment PL_markstack_ptr and PL_scopestack_ix. This was added back in 1997 in the era of unsafe signals, to make them slightly less unsafe. The idea presumably was to stop signal handlers inadvertently corrupting the top element of each stack. However, given that the normal method of pushing something onto those stacks is to increment the pointer before pushing the value, I don't see how that can happen. The downside of this is that an uninitialised or stale value can be left in the 'hole' left on these stacks. When exiting from a signal handler via exit(), these holes can be read and corruption occur, while stack unwinding is taking place. The ordering of things means we can't use SAVEDESTRUCTOR_X to undo the damage. This commit leaves the 'PL_savestack_ix += 5', because in this case, with unsafe signals, it *is* possible to interrupt halfway through a new set of save data being pushed onto the stack, and it *is* possible for this to be undone via SAVEDESTRUCTOR_X. (But it's still unsafe and half-baked.) This fixes [perl #85206].
-rw-r--r--mg.c15
1 files changed, 1 insertions, 14 deletions
diff --git a/mg.c b/mg.c
index 7b5fdf502b..447d86cdee 100644
--- a/mg.c
+++ b/mg.c
@@ -3035,14 +3035,6 @@ Perl_sighandler(int sig)
PL_savestack_ix += 5; /* Protect save in progress. */
SAVEDESTRUCTOR_X(S_unwind_handler_stack, NULL);
}
- if (PL_markstack_ptr < PL_markstack_max - 2) {
- flags |= 2;
- PL_markstack_ptr++; /* Protect mark. */
- }
- if (PL_scopestack_ix < PL_scopestack_max - 3) {
- flags |= 4;
- PL_scopestack_ix++;
- }
/* sv_2cv is too complicated, try a simpler variant first: */
if (!SvROK(PL_psig_ptr[sig]) || !(cv = MUTABLE_CV(SvRV(PL_psig_ptr[sig])))
|| SvTYPE(cv) != SVt_PVCV) {
@@ -3132,10 +3124,6 @@ Perl_sighandler(int sig)
cleanup:
/* pop any of SAVEFREESV, SAVEDESTRUCTOR_X and "save in progress" */
PL_savestack_ix = old_ss_ix;
- if (flags & 2)
- PL_markstack_ptr--;
- if (flags & 4)
- PL_scopestack_ix -= 1;
if (flags & 8)
SvREFCNT_dec(sv);
PL_op = myop; /* Apparently not needed... */
@@ -3221,8 +3209,7 @@ S_restore_magic(pTHX_ const void *p)
/* clean up the mess created by Perl_sighandler().
* Note that this is only called during an exit in a signal handler;
* a die is trapped by the call_sv() and the SAVEDESTRUCTOR_X manually
- * skipped over. This is why we don't need to fix up the markstack and
- * scopestack - they're going to be set to 0 anyway */
+ * skipped over. */
static void
S_unwind_handler_stack(pTHX_ const void *p)