diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-10-26 13:49:40 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-10-28 16:15:07 -0700 |
commit | 8465ba45245d0c78b43d10c2436bd926a67c99e9 (patch) | |
tree | a90192623441af8e112a541c007d5411ead9f783 | |
parent | 538c5178ddc0470ec56edd6c1ef5416c46f217c7 (diff) | |
download | perl-8465ba45245d0c78b43d10c2436bd926a67c99e9.tar.gz |
Make PL_firstgv and PL_secondgv refcounted
Otherwise freeing *a or *b in a sort block will result in a crash:
$ perl -e '@_=sort { delete $::{a}; 3 } 1..3'
Segmentation fault: 11
-rw-r--r-- | pp_sort.c | 12 | ||||
-rw-r--r-- | sv.c | 4 | ||||
-rw-r--r-- | t/op/sort.t | 7 |
3 files changed, 16 insertions, 7 deletions
@@ -1656,10 +1656,14 @@ PP(pp_sort) CATCH_SET(TRUE); PUSHSTACKi(PERLSI_SORT); if (!hasargs && !is_xsub) { - SAVESPTR(PL_firstgv); - SAVESPTR(PL_secondgv); - PL_firstgv = gv_fetchpvs("a", GV_ADD|GV_NOTQUAL, SVt_PV); - PL_secondgv = gv_fetchpvs("b", GV_ADD|GV_NOTQUAL, SVt_PV); + SAVEGENERICSV(PL_firstgv); + SAVEGENERICSV(PL_secondgv); + PL_firstgv = MUTABLE_GV(SvREFCNT_inc( + gv_fetchpvs("a", GV_ADD|GV_NOTQUAL, SVt_PV) + )); + PL_secondgv = MUTABLE_GV(SvREFCNT_inc( + gv_fetchpvs("b", GV_ADD|GV_NOTQUAL, SVt_PV) + )); SAVESPTR(GvSV(PL_firstgv)); SAVESPTR(GvSV(PL_secondgv)); } @@ -13845,8 +13845,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_errors = sv_dup_inc(proto_perl->Ierrors, param); PL_sortcop = (OP*)any_dup(proto_perl->Isortcop, proto_perl); - PL_firstgv = gv_dup(proto_perl->Ifirstgv, param); - PL_secondgv = gv_dup(proto_perl->Isecondgv, param); + PL_firstgv = gv_dup_inc(proto_perl->Ifirstgv, param); + PL_secondgv = gv_dup_inc(proto_perl->Isecondgv, param); PL_stashcache = newHV(); diff --git a/t/op/sort.t b/t/op/sort.t index 9eb3525b7c..dd60f97c22 100644 --- a/t/op/sort.t +++ b/t/op/sort.t @@ -6,7 +6,7 @@ BEGIN { require 'test.pl'; } use warnings; -plan( tests => 181 ); +plan( tests => 182 ); # these shouldn't hang { @@ -1011,3 +1011,8 @@ is $#a, 10, 'sort block modifying $a and $b'; () = sort { is \$a, \$a, '[perl #78194] op return values passed to sort'; 0 } "${\''}", "${\''}"; + +package deletions { + @_=sort { delete $deletions::{a}; delete $deletions::{b}; 3 } 1..3; +} +pass "no crash when sort block deletes *a and *b"; |