diff options
author | Artur Bergman <sky@nanisky.com> | 2003-04-19 00:40:42 +0000 |
---|---|---|
committer | Artur Bergman <sky@nanisky.com> | 2003-04-19 00:40:42 +0000 |
commit | b34402ddaa7fb5ef7e3c209ae505ec005d5a34dd (patch) | |
tree | e746ae67d348b8b3bcc770c0329e6f5cca04f095 /sv.c | |
parent | bf29be10504ebf4caff9a3799bc572cdca38918c (diff) | |
download | perl-b34402ddaa7fb5ef7e3c209ae505ec005d5a34dd.tar.gz |
Don't use the stack to allocate a SV that we hand out to another
function, only badness can ensure.
Message-Id: <20030418180131.GD10086@fdgroup.com>
Thanks go to Dave Mitchell for help in tracking down the bug!
p4raw-id: //depot/perl@19265
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 23 |
1 files changed, 13 insertions, 10 deletions
@@ -5309,34 +5309,37 @@ Perl_sv_clear(pTHX_ register SV *sv) if (PL_defstash) { /* Still have a symbol table? */ dSP; CV* destructor; - SV tmpref; - Zero(&tmpref, 1, SV); - sv_upgrade(&tmpref, SVt_RV); - SvROK_on(&tmpref); - SvREADONLY_on(&tmpref); /* DESTROY() could be naughty */ - SvREFCNT(&tmpref) = 1; + do { stash = SvSTASH(sv); destructor = StashHANDLER(stash,DESTROY); if (destructor) { + SV* tmpref = newRV(sv); + SvREADONLY_on(tmpref); /* DESTROY() could be naughty */ ENTER; PUSHSTACKi(PERLSI_DESTROY); - SvRV(&tmpref) = SvREFCNT_inc(sv); EXTEND(SP, 2); PUSHMARK(SP); - PUSHs(&tmpref); + PUSHs(tmpref); PUTBACK; call_sv((SV*)destructor, G_DISCARD|G_EVAL|G_KEEPERR|G_VOID); - SvREFCNT(sv)--; + + POPSTACK; SPAGAIN; LEAVE; + if(SvREFCNT(tmpref) < 2) { + /* tmpref is not kept alive! */ + SvREFCNT(sv)--; + SvRV(tmpref) = 0; + SvROK_off(tmpref); + } + SvREFCNT_dec(tmpref); } } while (SvOBJECT(sv) && SvSTASH(sv) != stash); - del_XRV(SvANY(&tmpref)); if (SvREFCNT(sv)) { if (PL_in_clean_objs) |