diff options
author | David Mitchell <davem@iabyn.com> | 2012-11-11 00:01:21 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2012-11-11 00:01:21 +0000 |
commit | 3d26b81e83dca7175e314b31d265a01e1e9b0320 (patch) | |
tree | 0353cf491729d1cb26db261c0ae9fd931dff5857 | |
parent | 285c5e4279bd1c29a0fad0f195fb22a65ac33ab2 (diff) | |
download | perl-3d26b81e83dca7175e314b31d265a01e1e9b0320.tar.gz |
make MULTICALL safe across cxstack reallocs
[perl #115602]
MUTLICALL sets a local var, cx, to point to the current context stack
frame. When a function is called, the context stack might be realloc()ed,
in which case cx would point to freed memory.
-rw-r--r-- | cop.h | 3 | ||||
-rw-r--r-- | ext/XS-APItest/t/multicall.t | 15 |
2 files changed, 16 insertions, 2 deletions
@@ -1217,7 +1217,8 @@ See L<perlcall/LIGHTWEIGHT CALLBACKS>. #define POP_MULTICALL \ STMT_START { \ - if (! ((CvDEPTH(multicall_cv) = cx->blk_sub.olddepth)) ) { \ + cx = &cxstack[cxstack_ix]; \ + if (! ((CvDEPTH(multicall_cv) = cx->blk_sub.olddepth)) ) { \ LEAVESUB(multicall_cv); \ } \ POPBLOCK(cx,PL_curpm); \ diff --git a/ext/XS-APItest/t/multicall.t b/ext/XS-APItest/t/multicall.t index 983f5fd016..f96f62e743 100644 --- a/ext/XS-APItest/t/multicall.t +++ b/ext/XS-APItest/t/multicall.t @@ -7,7 +7,7 @@ use warnings; use strict; -use Test::More tests => 6; +use Test::More tests => 7; use XS::APItest; @@ -48,3 +48,16 @@ use XS::APItest; is($destroyed, 1, "f now destroyed"); } + +# [perl #115602] +# deep recursion realloced the CX stack, but the dMULTICALL local var +# 'cx' still pointed to the old one. +# Thius doesn;t actually test the failure (I couldn't think of a way to +# get the failure to show at the perl level) but it allows valgribnd or +# similar to spot any errors. + +{ + sub rec { my $c = shift; rec($c-1) if $c > 0 }; + my @r = XS::APItest::multicall_each { rec(90) } 1,2,3; + pass("recursion"); +} |